import sys from time import strftime, gmtime from twisted.internet import reactor from twisted.web.server import Site from twisted.web.resource import Resource from twisted.web.static import File import paho.mqtt.client as mqtt import json LOGFILE_pre = '/tmp/' APP_LOGFILE = LOGFILE_pre + 'laundry.log' SERVER_LOGFILE = LOGFILE_pre + 'laundryServer.log' TOPIC_RELAYBOX_STATE = "IoT/Status/RelayBox" TOPIC_PARSEDDATA_pre = "IoT/ParsedData" TOPIC_PARSEDDATA = TOPIC_PARSEDDATA_pre + "/#" switchMapping = { 'oven': { 'index': 1, 'label': 'Herd' }, 'laundry': { 'index': 2, 'label': 'Waschkueche' }, 'kitchen': { 'index': 0, 'label': 'Kueche' }, 'lightbasem': { 'index': 3, 'label': 'Licht Keller' }, 'light1flr': { 'index': 4, 'label': 'Licht EG' }, 'light2flr': { 'index': 5, 'label': 'Licht OG' }, } loadedSwitchStates = ['x0', 'x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7'] measurementValues = {} def log(m): t = strftime("%d %b %Y %H:%M:%S", gmtime()) with open(APP_LOGFILE, 'a') as f: f.write("%s %s\n" % (t, m)) def on_message(client, userdata, msg): topic = msg.topic if (topic == TOPIC_RELAYBOX_STATE): j = json.loads(msg.payload) ss = j['data']['switchStates'] for s in ss: if s['feedbackState'] == 0: loadedSwitchStates[s['index']] = 'aus' elif s['state'] == 1: loadedSwitchStates[s['index']] = 'an' else: loadedSwitchStates[s['index']] = 'unbekannt' elif (topic.startswith(TOPIC_PARSEDDATA_pre)): j = json.loads(msg.payload) data = j['data'] metadata = j['metadata'] if ('category' in metadata): category = metadata['category'] else: if (('device' in metadata) and ('Slave' in metadata) and (metadata['device'] == 'ModbusHub') and (metadata['Slave'] == 'Thermometer')): category = 'FreezeThermometer' if (category in ['OnePhaseElectric_Finder', 'ThreePhaseElectric_Finder']): measurementValues[metadata['name']] = [ {'label': 'Leistung', 'value': data['power']}, {'label': 'Verbrauch', 'value': data['energy']}, {'label': 'Strom', 'value': data['current']}, ] elif (category == 'Watermeter_Hyd'): measurementValues[metadata['name']] = [ {'label': 'Durchfluss', 'value': data['flow']}, {'label': 'Verbrauch', 'value': data['volume']}, {'label': 'Temperatur', 'value': data['temperature']}, ] elif (category == 'OS'): measurementValues[metadata['name']] = [ {'label': '1min', 'value': data['loadavg'][0]}, {'label': '5min', 'value': data['loadavg'][1]}, {'label': '15min', 'value': data['loadavg'][2]}, {'label': 'Uptime', 'value': data['uptime']}, ] elif (category == 'Thermometer_Hottis'): measurementValues[metadata['name']] = [ {'label': 'Temperatur Aussen', 'value': data['temperature2']}, {'label': 'Temperatur Haus', 'value': data['temperature4']}, {'label': 'Temperatur Innen', 'value': data['temperature3']}, {'label': 'Uptime', 'value': data['operatingTime']}, ] elif (category == 'FreezeThermometer'): measurementValues[metadata['name']] = [ {'label': 'Temperatur Gefrierschrank', 'value': data['t2']}, {'label': 'Temperatur Kuehlschrank', 'value': data['t1']}, ] else: log('unexpected category') class MyResource(Resource): def log(self, m): log(m) def send_message(self, target, switchState): try: cs = ['off', 'on'] t = int(target) s = int(switchState) if s not in [0, 1]: raise ValueError('illegal switchState ' + switchState) if t < 0 or t >= len(loadedSwitchStates): raise ValueError('illegal target ' + target) command = "switch %d %s" % (t, cs[s]) mqttClient.publish('IoT/Command/RelayBox', command) #mqttClient.publish('IoT/x', command) self.log(command) except ValueError, e: self.log("ValueError in send_message: " + str(e)) class HelloWorld(MyResource): isLeaf = True def render_GET(self, request): return "Hello world!" class SwitchCommand(MyResource): isLeaf = True def render_GET(self, request): res = "ERR" try: target = request.args['target'][0] switchState = request.args['state'][0] self.send_message(target, switchState) res = "OK" except KeyError, e: self.log("KeyError in SwitchCommand, render_GET: " + str(e)) return res class SwitchStatus(MyResource): isLeaf = False def render_GET(self, request): state = "ERR" try: target = request.args['target'][0] t = int(target) state = loadedSwitchStates[t] except ValueError, e: self.log("ValueError in SwitchStatus, render_GET: " + str(e)) except KeyError, e: self.log("KeyError in SwitchStatus, render_GET: " + str(e)) except IndexError, e: self.log("KeyError in SwitchStatus, render_GET: " + str(e)) return state class SwitchMapping(MyResource): isLeaf = False def render_GET(self, request): return json.dumps(switchMapping,indent=2, separators=(',', ': ')) class MeasurementValues(MyResource): isLeaf = False def render_GET(self, request): return json.dumps(measurementValues,indent=2, separators=(',', ': ')) mqttClient = mqtt.Client() mqttClient.on_message = on_message mqttClient.connect("mqttbroker", 1883, 60) mqttClient.subscribe(TOPIC_RELAYBOX_STATE) mqttClient.subscribe(TOPIC_PARSEDDATA) mqttClient.loop_start() root = Resource() root.putChild("", File("index.html")) root.putChild("Hello", HelloWorld()) root.putChild("switchCommand", SwitchCommand()) root.putChild("switchStatus", SwitchStatus()) root.putChild("switchMapping", SwitchMapping()) root.putChild("measurementValues", MeasurementValues()) factory = Site(root, logPath=SERVER_LOGFILE) reactor.listenTCP(8080, factory) reactor.run()