How do I retrieve a file from the Device Cloud with a Digi Python script?
All the examples I have seen only send files out to the Device Cloud.
I know this is possible with an http call. Is there a better way to do this natively on a digi device?
How do I retrieve a file from the Device Cloud with a Digi Python script?
All the examples I have seen only send files out to the Device Cloud.
I know this is possible with an http call. Is there a better way to do this natively on a digi device?
Hello
The following is a python script that I wrote and use for training. It requests a file from the cloud. It then uses DOM to âpick the file apartâ The second part might be more than you need. But hopefully this will give you a start.
I donât know how to attach a file so (unfortunately) I am just dumping the python into the response.
The file name was request_furnace_data_file.py as it was part of an application. You can call it anything you want. The parameters are username, password, device id (the FULL device id) , file name. So it will look for a file associated with a device.
import httplib
import base64
import sys
from xml.dom.minidom import parseString
from xml.dom.minidom import Node
import os
import re
from time import sleep, ctime
def Usage():
print 'Usage: request_furnace_data_file.py
â
def handleChildren(theDOMObject):
theChildList = theDOMObject.childNodes
#translateNodeType(theDOMObject.nodeType)
if theDOMObject.nodeType == Node.ELEMENT_NODE:
print 'Element node â + theDOMObject.nodeName
# for each child node look for text non-empty text nodes to print out
for aChildFromThisList in theChildList:
# An element node can have text nodes with no data. They have a carriage return as the text
# lets weed them out, otherwise could be valid text or attribute
# strip will remove all white space, carriage returns and line feeds included. Only print out
# text nodes that have something after being stripped
if aChildFromThisList.nodeType == Node.TEXT_NODE and len(aChildFromThisList.nodeValue.strip()) > 0:
# when we actually print out the data, do not include all of the crud
print 'Value â + aChildFromThisList.nodeValue.strip()
if len(theChildList) == 0 and theDOMObject.nextSibling == None:
return
for theChildNode in theChildList:
if theChildNode.nodeType == Node.ELEMENT_NODE:
# for now we will not worry about attributes
if theChildNode.hasAttributes() == True:
handleAttributes(theChildNode)
#print âwould have handled attributesâ
# iterate through the children of our present node
thisNodeHasChildren = theChildNode.hasChildNodes()
# only process if this child has children
if thisNodeHasChildren == True:
numChildren = len(theChildNode.childNodes)
tempChildren = theChildNode.childNodes
# look for element nodes that we will handle recursively
if theChildNode.nodeType == Node.ELEMENT_NODE:
handleChildren(theChildNode)
def parseTheFileData(theFileData, theTag):
print â in parseTheFileData, we are looking starting at â + theTag
print theFileData
myXMLDom = parseString(theFileData)
memberList = []
memberList = myXMLDom.getElementsByTagName(theTag)
print âFound " + str(len(memberList)) + " " + theTag + " elementsâ
for theNextMember in memberList:
print âCalling handleChildren from parseTheFileDataâ
handleChildren(theNextMember)
def SendMessage(username, password, deviceid, filename):
auth = base64.encodestring(â%s:%sâ%(username,password))[:-1]
webservice = httplib.HTTP(âlogin.etherios.comâ,80)
myParams = (deviceid, filename)
theRequest = âââ/ws/FileData/~/%s/%sâââ % myParams
print "theRequest holds " + theRequest
webservice.putrequest(âGETâ, theRequest)
webservice.putheader(âAuthorizationâ, âBasic %sâ%auth)
webservice.putheader(âAcceptâ, âtext/htmlâ)
webservice.putheader(âAcceptâ, âtext/plainâ)
webservice.putheader(âAcceptâ, âtext/xmlâ)
webservice.endheaders()
try:
theStatusCode, theStatusMessage, header = webservice.getreply()
# get the file contents
response_body = webservice.getfile().read()
# for yucks print out the reqponse
print (theStatusCode, theStatusMessage)
# print out the file data
print "File contents:
"
print " "
print response_body
except urllib2.HTTPError, e:
print 'HTTP Error â + str(e.code)
except urllib2.URLError, e:
print 'URL Error â + str(e.reason)
if theStatusCode == 200:
# if the request was successful, parse the file contents
print âgot a file from the cloudâ
parseTheFileData(response_body, âfurnaceDataRecordâ)
else:
# if the request failed, just print a message
print âUnable to get a file from the cloudâ
def main(argv):
try:
iterationCount = 0
#process arguments
count = len(argv);
if count != 4:
Usage()
else:
SendMessage(argv[0], argv[1], argv[2], argv[3])
except KeyboardInterrupt:
print âExecution halted by user actionâ
if name == âmainâ:
sys.exit(main(sys.argv[1:]))
Thank you that is very helpful.
I guess I am a little confused why the SDK examples to send a file use a Device Cloud library call âdc_data.send_dc_dataâ. But there doesnât seem to be any support for other calls to do much else.
Doing everything with HTTP seems kinda weird when the device already has a persistent connection to the Device CloudâŚ
Are you trying to pull a file down to a PC or are you trying to have a device pull a file from the cloud to itself. The script I provided would be used to pull a file, pushed up by a device to the cloud, from the cloud. If you are looking to have a device pull down a file, then maybe there is another method for doing so.
I would like to pull a file from the Device Cloud to a WR21. Your method would probably work, but I donât think itâs the best way.
Support says this must be done via an HTTP call and the Device Cloud can not be easily accessed via the existing socket connection for this functionality. Somewhat disappointing, but this is the answerâŚ