Commit 6cc98257328cf34c200d0ea0ebae6c5715e13504

Authored by mik
0 parents
Exists in master

first commit

Showing 2 changed files with 204 additions and 0 deletions Side-by-side Diff

... ... @@ -0,0 +1,9 @@
  1 +
  2 +
  3 +try -h for help
  4 +-v for verbose
  5 +
  6 +
  7 +needs mqtt, redis
  8 +
  9 +gives: json output
devlolhackerspaceapi.py
... ... @@ -0,0 +1,195 @@
  1 +#!/usr/bin/python3
  2 +
  3 +from http.server import BaseHTTPRequestHandler,HTTPServer
  4 +
  5 +import paho.mqtt.client as paho
  6 +import logging,sys
  7 +import redis
  8 +import time
  9 +import json
  10 +
  11 +import argparse
  12 +
  13 +
  14 +sensors = {}
  15 +sensors['door_locked'] = [
  16 + {"topic":"devlol/h19/door/lockstatus","valuetype":"doorboolean","location":"Front door"}
  17 + ]
  18 +sensors['temperature'] = [
  19 + {"topic":"devlol/h19/mainroom/temperature","unit":"°C","location":"main room"},
  20 + {"topic":"devlol/h19/dungeon/DHT21/temp","unit":"°C","location":"dungeon"},
  21 + ]
  22 +sensors['humidity'] = [
  23 + {"topic":"devlol/h19/mainroom/humidity","unit":"%","location":"main room"},
  24 + {"topic":"devlol/h19/dungeon/DHT21/hum","unit":"%","location":"dungeon"},
  25 + ]
  26 +sensors['people_now_present'] = [
  27 + {"topic":"devlol/h19/mainroom/headcount"},
  28 + ]
  29 +sensors['network_connections'] = [
  30 + {"topic":"devlol/h19/mainroom/dhcpleases","valuetype":"int"},
  31 + ]
  32 +
  33 +class MyHandler(BaseHTTPRequestHandler):
  34 +
  35 + def do_HEAD(client):
  36 + client.send_response(200)
  37 + client.send_header("Content-type", "text/html")
  38 + client.end_headers()
  39 +
  40 + def do_GET(self):
  41 + if self.path == "/":
  42 + self.send_response(200)
  43 + self.send_header("Content-type", "application/json")
  44 + self.end_headers()
  45 + try:
  46 + self.wfile.write(str.encode(generate_hackerspaceapi_json()))
  47 + except BrokenPipeError:
  48 + pass
  49 +
  50 +def on_message(client, userdata, msg):
  51 + global r
  52 + payload = msg.payload.decode("utf-8")
  53 + logging.debug("received mqtt: " + msg.topic + " payload: " + payload)
  54 + r.set (msg.topic,payload)
  55 + r.set (msg.topic+':timestamp',int(time.time()))
  56 +
  57 +def on_disconnect(client, userdata, foo):
  58 + connected = False
  59 + while not connected:
  60 + try:
  61 + client.reconnect()
  62 + connected = True
  63 + # resubscribe to the topics
  64 + client = mqtt_subscribe(client)
  65 + except:
  66 + logging.error("Failed to reconnect mqtt...")
  67 + time.sleep(1)
  68 +
  69 +def on_connect(client, userdata, foo):
  70 + logging.debug ("on_connect fired")
  71 + global sensors
  72 + for sensortype in sensors:
  73 + for sensor in sensors[sensortype]:
  74 + client.subscribe(sensor['topic'])
  75 + logging.debug ("subscribing to mqtt-topic: " + sensor['topic'])
  76 +
  77 +def generate_hackerspaceapi_json():
  78 + global r
  79 +
  80 + apiresponse = { "api": "0.13",
  81 + "space": "DevLoL",
  82 + "url": "https://devlol.org",
  83 + "logo": "http://devlol.org/static_wiki/DevLoL.png",
  84 + "cache": {
  85 + "schedule": "m.02"
  86 + },
  87 + "contact": {
  88 + "irc": "ircs://irc.servus.at:6667/devlol",
  89 + "ml": "devlol-orga@lists.servus.at"
  90 + },
  91 + "issue_report_channels": [
  92 + "ml"
  93 + ],
  94 + "location": {
  95 + "address": "Hofgasse 19, 4020 Linz, Austria",
  96 + "lat": 48.30573,
  97 + "lon": 14.28383
  98 + },
  99 + "sensors": {
  100 + }
  101 + }
  102 +
  103 + for sensortype in sensors:
  104 + apiresponse['sensors'][sensortype]=[]
  105 + for sensor in sensors[sensortype]:
  106 + try:
  107 + try:
  108 + if sensor['valuetype'] == 'int':
  109 + value = int(str(r.get(sensor['topic']),'utf-8'))
  110 + if sensor['valuetype'] == 'string':
  111 + value = str(r.get(sensor['topic']),'utf-8')
  112 + if sensor['valuetype'] == 'doorboolean':
  113 + if str(r.get(sensor['topic']),'utf-8') == "UNLOCKED":
  114 + value = False
  115 + else: value = True
  116 + except:
  117 + value = float(str(r.get(sensor['topic']),'utf-8'))
  118 + validvalue = True
  119 + except:
  120 + validvalue = False
  121 +
  122 + if validvalue:
  123 + sensortemp={}
  124 + for sensorproperty in sensor:
  125 + if sensorproperty != 'topic' and sensorproperty !='valuetype':
  126 + sensortemp[sensorproperty] = sensor[sensorproperty]
  127 +
  128 + sensortemp['value'] = value
  129 +
  130 + apiresponse['sensors'][sensortype].append( sensortemp )
  131 +
  132 +
  133 + try:
  134 + if str(r.get('devlol/h19/door/lockstatus'),'utf-8') == 'UNLOCKED':
  135 + statevalue = True
  136 + else:
  137 + statevalue = False
  138 + statechange = int(str(r.get('devlol/h19/door/lockstatus:timestamp'),'utf-8'))
  139 + except:
  140 + statevalue = False
  141 + statechange = 0
  142 +
  143 + apiresponse['state'] = {'open':statevalue,'lastchange':statechange}
  144 +
  145 +
  146 + try:
  147 + resp = json.dumps(apiresponse,sort_keys=True,indent=4)
  148 + except:
  149 + resp = json.dumps('{}')
  150 + return resp
  151 +
  152 +
  153 +def run(server_class=HTTPServer,
  154 + handler_class=MyHandler):
  155 +
  156 + global r
  157 + parser = argparse.ArgumentParser()
  158 + parser.add_argument("-p", default=8322, help="port to bind to", type=int)
  159 + parser.add_argument("-v", "--verbose", help="increase output verbosity", action="store_true")
  160 + parser.add_argument("--mqtthost", default="mqtt.devlol.org", help="which mqtt broker to connect to")
  161 + parser.add_argument("--redishost", default="127.0.0.1", help="which redis to connect to")
  162 + args = parser.parse_args()
  163 + port = args.p
  164 +
  165 + if args.verbose:
  166 + logging.basicConfig(level=logging.DEBUG)
  167 + else:
  168 + logging.basicConfig(level=logging.ERROR)
  169 +
  170 + ## setup redis
  171 + r = redis.StrictRedis(host=args.redishost, port=6379, db=0)
  172 +
  173 + ## setup MQTT client
  174 + client = paho.Client()
  175 + client.on_connect = on_connect
  176 + client.on_message = on_message
  177 + client.on_disconnect = on_disconnect
  178 + client.loop_start()
  179 +
  180 + try:
  181 + client.connect(args.mqtthost)
  182 + logging.info ("connected to mqtt")
  183 + except:
  184 + logging.error("failed to connect to mqtt")
  185 + on_disconnect(client, None, None)
  186 +
  187 + server_address = ('', port)
  188 + httpd = server_class(server_address, handler_class)
  189 + logging.info ("listening to http on port:" + str(port))
  190 +
  191 + while True:
  192 + httpd.handle_request()
  193 +
  194 +if __name__ == "__main__":
  195 + run()