# HG changeset patch
# User drewp@bigasterisk.com
# Date 1484614450 28800
# Node ID 629cd8c36831b3083ecbf6e698b846cae9b61515
# Parent 02d9915b3bbbfad1b51c4d1479f11495ba46ac2e
rewrite to cyclone. sends data to influx
Ignore-this: 1c842a1ddee0a0601497ff54121baaeb
diff -r 02d9915b3bbb -r 629cd8c36831 service/dpms/dpms.py
--- a/service/dpms/dpms.py Fri Nov 25 17:56:26 2016 -0800
+++ b/service/dpms/dpms.py Mon Jan 16 16:54:10 2017 -0800
@@ -21,8 +21,10 @@
"""
-from bottle import run, get, put, request, response
-import subprocess, sys, socket
+from twisted.internet import reactor, task
+import cyclone.web
+from influxdb import InfluxDBClient
+import subprocess, sys, socket, time, os
from rdflib import Namespace, URIRef
DEV = Namespace("http://projects.bigasterisk.com/device/")
ROOM = Namespace("http://projects.bigasterisk.com/room/")
@@ -32,51 +34,84 @@
sys.path.append("../../lib")
from localdisplay import setDisplayToLocalX
+influx = InfluxDBClient('bang6', 9060, 'root', 'root', 'main')
+
def getMonitorState():
out = subprocess.check_output(['xset', 'q'])
for line in out.splitlines():
line = line.strip()
if line == 'Monitor is On':
- response.set_header('content-type', 'text/plain')
return 'on'
elif line in ['Monitor is Off', 'Monitor is in Suspend', 'Monitor is in Standby']:
- response.set_header('content-type', 'text/plain')
return 'off'
raise NotImplementedError("no matching monitor line in xset output")
-@get("/")
-def index():
- getMonitorState() # to make it fail if xset isn't working
- return '''
- Get and put the monitor power with dpms.
- rdf graph available.'''
+class Root(cyclone.web.RequestHandler):
+ def get(self):
+ getMonitorState() # to make it fail if xset isn't working
+ self.write('''
+ Get and put the monitor power with dpms.
+ rdf graph available.''')
-@get("/monitor")
-def monitor():
- return getMonitorState()
+class Monitor(cyclone.web.RequestHandler):
+ def get(self):
+ self.set_header('content-type', 'text/plain')
+ self.write(getMonitorState())
+
+ def put(self):
+ body = self.request.body.strip()
+ if body in ['on', 'off']:
+ subprocess.check_call(['xset', 'dpms', 'force', body])
+ self.set_status(204)
+ else:
+ raise NotImplementedError("body must be 'on' or 'off'")
+
-@put("/monitor")
-def putMonitor():
- body = request.body.read().strip()
- if body in ['on', 'off']:
- subprocess.check_call(['xset', 'dpms', 'force', body])
- response.status = 204
- else:
- raise NotImplementedError("body must be 'on' or 'off'")
- return ''
+class Graph(cyclone.web.RequestHandler):
+ def get(self):
+ host = socket.gethostname()
+ g = StateGraph(ctx=DEV['dpms/%s' % host])
+ g.add((URIRef("http://bigasterisk.com/host/%s/monitor" % host),
+ ROOM['powerStateMeasured'],
+ ROOM[getMonitorState()]))
+
+ self.set_header('Content-type', 'application/x-trig')
+ self.write(g.asTrig())
+
-@get("/graph")
-def graph():
- host = socket.gethostname()
- g = StateGraph(ctx=DEV['dpms/%s' % host])
- g.add((URIRef("http://bigasterisk.com/host/%s/monitor" % host),
- ROOM['powerStateMeasured'],
- ROOM[getMonitorState()]))
-
- response.set_header('Content-type', 'application/x-trig')
- return g.asTrig()
+class Poller(object):
+ def __init__(self):
+ self.lastSent = None
+ self.lastSentTime = 0
+ task.LoopingCall(self.poll).start(5)
+
+ def poll(self):
+ now = int(time.time())
+ try:
+ state = getMonitorState()
+ except subprocess.CalledProcessError, e:
+ print repr(e)
+ os.abort()
+ if state != self.lastSent or (now > self.lastSentTime + 3600):
+ influx.write_points([
+ {'measurement': 'power',
+ 'tags': {'device': '%sMonitor' % socket.gethostname()},
+ 'fields': {'value': 1 if state == 'on' else 0},
+ 'time': now
+ }], time_precision='s')
+
+ self.lastSent = state
+ self.lastSentTime = now
setDisplayToLocalX()
+poller = Poller()
+
+reactor.listenTCP(9095, cyclone.web.Application([
+ (r'/', Root),
+ (r'/monitor', Monitor),
+ (r'/graph', Graph),
+]), interface='::')
-run(host="[::]", server='gunicorn', port=9095, quiet=True)
+reactor.run()
+