Skip to content

Commit

Permalink
Improved JSON support, removed XML support
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Franske committed Nov 14, 2014
1 parent b1e690c commit c8a7ac1
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 133 deletions.
42 changes: 15 additions & 27 deletions pystat.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ def getperiodsched(self, day, period):
settings = self.getLine(tstat_address,local_address,self.commands['scheduleentry'] + str(day) + '/' + str(period),'?')
data = settings.split()
parsedData = {}
parsedData['day'+str(day)+'_period'+str(period)] = {}
pythonDOW = str(day-1)
for i in data:
subdata = i.split("=")
Expand All @@ -232,42 +233,29 @@ def getperiodsched(self, day, period):
# elif subdata[0] == "O":
# parsedData['originator']=subdata[1]
if subdata[0] == self.commands['scheduleentry'] + str(day) + '/' + str(period):
parsedData['schedTime']=strptime(pythonDOW + subdata[1][0:4],"%w%H%M")
parsedData['setpointHeating']=subdata[1][4:6]
parsedData['setpointCooling']=subdata[1][6:8]
parsedData['rcs_period_number']=period
parsedData['rcs_day_number']=day
parsedData['day'+str(day)+'_period'+str(period)]['schedTime']=strptime(pythonDOW + subdata[1][0:4],"%w%H%M")
parsedData['day'+str(day)+'_period'+str(period)]['setpointHeating']=int(subdata[1][4:6])
parsedData['day'+str(day)+'_period'+str(period)]['setpointCooling']=int(subdata[1][6:8])
parsedData['day'+str(day)+'_period'+str(period)]['rcs_period_number']=int(period)
parsedData['day'+str(day)+'_period'+str(period)]['rcs_day_number']=int(day)
return parsedData
def getdaysched(self, day):
# Return an array with the daily schedule for the given day (given numerically where Sun=1, Sat=7)
# Return an array with all four periods in the given day (given numerically where Sun=1, Sat=7)
daysched = {}
for i in range(1,5):
daysched['period'+str(i)]=self.getperiodsched(day, i)
daysched.update(self.getperiodsched(day, i))
return daysched
def getweeksched(self):
# Return an array with the complete weekly schedule (where Sun=1, Sat=7)
weeksched = {}
for i in range(1,8):
weeksched['day'+str(i)]=self.getdaysched(i)
weeksched.update(self.getdaysched(i))
return weeksched
def setperiodsched(self, schedule):
# Accepts an array with the entries for a given day and period in the same format as getperiodsched returns
def setsched(self, schedule):
# Accepts an array with the entries for a one or more days and periods in the same format as getperiodsched returns
# Note that schedTime is in the python struct_time format (with only hour, minute and weekday used)
day=int(strftime("%w",schedule['schedTime']))+1
time=strftime("%H%M",schedule['schedTime'])
status = self.sendBasicSet(tstat_address,local_address,self.commands['scheduleentry'] + str (day) + '/' + str(schedule['rcs_period_number']),time + schedule['setpointHeating'] + schedule['setpointCooling'])
return
def setdaysched(self, schedule):
# Accepts a multi-dimensional array with the entries for all periods of a given day in the same format as getdaysched returns
# Note that schedTime is in the python struct_time format (with only hour, minute and weekday used)
daysched = {}
for i in range(1,5):
self.setperiodsched(schedule[i])
return
def setweeksched(self, schedule):
# Accepts a multi-dimensional array with the entries for all periods of all days in the same format as getweeksched returns
# Note that schedTime is in the python struct_time format (with only hour, minute and weekday used)
daysched = {}
for i in range(1,8):
self.setdaysched(schedule[i])
for period in schedule:
day=int(strftime("%w",schedule[period]['schedTime']))+1
time=strftime("%H%M",schedule[period]['schedTime'])
status = self.sendBasicSet(tstat_address,local_address,self.commands['scheduleentry'] + str (day) + '/' + str(schedule[period]['rcs_period_number']),time + str(schedule[period]['setpointHeating']) + str(schedule[period]['setpointCooling']))
return
160 changes: 54 additions & 106 deletions schedStat.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,110 +8,62 @@
from lxml import etree
from time import localtime, strftime, strptime

def convertWeekToXML(weekSched):
# Returns an XML etree version of the weekSched array
root = etree.Element("schedule")
day = {}
day_number = {}
day_name = {}

for i in sorted(weekSched):
day[i] = etree.SubElement(root, "day")
# Get the current day number from the time_struct of the first period
day_number[i] = etree.SubElement(day[i], "day_number").text = str(int(strftime("%w",weekSched[i]['period1']['schedTime']))+1)
# Save the current day name to make the XML more human-readable but this is NOT used anythere, only the day_number is!
day_name[i] = etree.SubElement(day[i], "day_name").text = strftime("%A",weekSched[i]['period1']['schedTime'])

period = {}
period_number = {}
period_setpointHeating = {}
period_setpointCooling = {}
period_schedTime = {}

for k in sorted(weekSched[i]):
period[k] = etree.SubElement(day[i], "period")
period_number[k] = etree.SubElement(period[k], "period_number").text = str(weekSched[i][k]['rcs_period_number'])
period_schedTime[k] = etree.SubElement(period[k], "schedTime").text = strftime("%H%M",weekSched[i][k]['schedTime'])
period_setpointHeating[k] = etree.SubElement(period[k], "setpointHeating").text = str(weekSched[i][k]['setpointHeating'])
period_setpointCooling[k] = etree.SubElement(period[k], "setpointCooling").text = str(weekSched[i][k]['setpointCooling'])

return root

def convertWeekToJSON(weekSched):
# Returns a JSON string version of the weekSched array
jsonWeekSched = {}
for day in weekSched:
jsonWeekSched[day] = {}
for period in weekSched[day]:
jsonWeekSched[day][period] = {}
for item in weekSched[day][period]:
jsonWeekSched[day][period][item] = {}
if item=='schedTime':
jsonWeekSched[day][period][item]=strftime("%H%M",weekSched[day][period]['schedTime'])
else:
jsonWeekSched[day][period][item]=weekSched[day][period][item]
for period in weekSched:
jsonWeekSched[period] = {}
for item in weekSched[period]:
jsonWeekSched[period][item] = {}
if item=='schedTime':
jsonWeekSched[period][item]=strftime("%H%M",weekSched[period]['schedTime'])
else:
jsonWeekSched[period][item]=weekSched[period][item]
return jsonWeekSched

def convertXMLToWeek(weekXML):
# Returns a week-style array of the XML data
weekSched = {}
i = 1
for day in weekXML:
k = 1
daySched = {}
for period in day:
periodSched = {}
# Day number is here
if period.tag == 'day_number':
day_number = int(period.text)
for element in period:
# Period number, time and setpoints are here
if element.tag == 'period_number':
periodSched['period'] = int(element.text)
if element.tag == 'setpointCooling':
periodSched['setpointCooling'] = element.text
if element.tag == 'setpointHeating':
periodSched['setpointHeating'] = element.text
if element.tag == 'schedTime':
schedTime = element.text
pythonDOW = str(day_number-1)
periodSched['schedTime'] = strptime(pythonDOW + schedTime,"%w%H%M")
if period.tag == 'period':
daySched[k] = periodSched
k += 1
weekSched[i] = daySched
i += 1
return weekSched
def convertJsonToSched(jsonSched):
# Returns a schedule style python array of the JSON data
schedule = {}
for period in jsonSched:
schedule[period] = {}
for item in jsonSched[period]:
schedule[period][item] = {}
if item=='schedTime':
schedule[period][item]=strptime(str(int(jsonSched[period]['rcs_day_number'])-1) + jsonSched[period]['schedTime'],"%w%H%M")
else:
schedule[period][item]=int(jsonSched[period][item])
return schedule

def saveSched(fileName,format):
# t = pystat.thermostat('/dev/ttyUSB0')
# weeksched=t.getweeksched()
# t.close()
weeksched=getSched()
if format=="xml":
etree.ElementTree(convertWeekToXML(weeksched)).write(fileName, pretty_print=True)
def saveSched(weeksched,fileName):
with open(fileName, 'w') as outfile:
json.dump(convertWeekToJSON(weeksched),outfile,indent=4,sort_keys=True)
outfile.close()
return

def loadSched(fileName,format):
weekXML = etree.parse(fileName).getroot()
t = pystat.thermostat('/dev/ttyUSB0')
if format=="xml":
t.setweeksched(convertXMLToWeek(weekXML))
t.close()
return
def loadSched(fileName):
with open(fileName, 'r') as infile:
schedule=convertJsonToSched(json.load(infile))
infile.close()
return schedule

def getSched():
t = pystat.thermostat('/dev/ttyUSB0')
weeksched=t.getweeksched()
t.close()
return weeksched

def stoutSched(format):
weeksched=getSched()
if format=="xml":
etree.ElementTree(convertWeekToXML(weeksched)).write(sys.stdout, pretty_print=True)
if format=="json":
print json.dumps(convertWeekToJSON(weeksched),indent=4,sort_keys=True)
def setSched(schedule):
t = pystat.thermostat('/dev/ttyUSB0')
t.setsched(schedule)
t.close()
return

def stinSched():
schedule=convertJsonToSched(json.loads(sys.stdin.read()))
return schedule

def stoutSched(weeksched):
print json.dumps(convertWeekToJSON(weeksched),indent=4,sort_keys=True)
return

def main():
Expand All @@ -122,28 +74,24 @@ def main():
metavar="FILE", help="Save the current weekly schedule to FILE")
parser.add_option("-l", "--load",
action="store", type="string", dest="loadFile",
metavar="FILE", help="Load the weekly schedule from FILE")
metavar="FILE", help="Load one or more periods from FILE")
parser.add_option("-o", "--stout",
action="store_true", dest="stout",
help="Send the current weekly schedule to standard output")
parser.add_option("-j", "--json",
action="store_true", dest="json", default=False,
help="Use JSON format input/output")
parser.add_option("-x", "--xml",
action="store_true", dest="xml", default=True,
help="Use XML format input/output")
parser.add_option("-i", "--stin",
action="store_true", dest="stin",
help="Load one or more periods from standard input")
(options, args) = parser.parse_args()
if options.json:
format="json"
elif options.xml:
format="xml"
if options.saveFile:
saveSched(options.saveFile,format)
if options.saveFile or options.stout:
weeksched=getSched()
if options.saveFile:
saveSched(weeksched,options.saveFile)
if options.stout:
stoutSched(weeksched)
elif options.loadFile:
loadSched(options.loadFile,format)
if options.stout:
stoutSched(format)

setSched(loadSched(options.loadFile))
elif options.stin:
setSched(stinSched())
if __name__ == "__main__":
main()

0 comments on commit c8a7ac1

Please sign in to comment.