RelayBoxWebApp/LaundryServer.py
2016-07-06 22:36:47 +02:00

197 lines
7.1 KiB
Python

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()