comparison service/dpms/dpms_service.py @ 464:1007ca70c34d

use PatchableGraph Ignore-this: dc954906750062923ef8205f8a8e8952
author drewp@bigasterisk.com
date Sat, 20 Apr 2019 23:38:56 -0700
parents 6c5303b85948
children a93fbf0d0daa
comparison
equal deleted inserted replaced
463:1ceb26846eca 464:1007ca70c34d
24 from twisted.internet import reactor, task 24 from twisted.internet import reactor, task
25 import cyclone.web 25 import cyclone.web
26 from influxdb import InfluxDBClient 26 from influxdb import InfluxDBClient
27 import subprocess, sys, socket, time, os 27 import subprocess, sys, socket, time, os
28 from rdflib import Namespace, URIRef 28 from rdflib import Namespace, URIRef
29 from logsetup import log, enableTwistedLog
30
31 from dpms import DPMS, DPMSModeOn
29 DEV = Namespace("http://projects.bigasterisk.com/device/") 32 DEV = Namespace("http://projects.bigasterisk.com/device/")
30 ROOM = Namespace("http://projects.bigasterisk.com/room/") 33 ROOM = Namespace("http://projects.bigasterisk.com/room/")
31 34
32 sys.path.append("/my/site/magma") 35 sys.path.append("/my/site/magma")
33 from stategraph import StateGraph 36 from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler
34 sys.path.append("../../lib") 37 #sys.path.append("../../lib")
35 from localdisplay import setDisplayToLocalX 38 #from localdisplay import setDisplayToLocalX
36 39
37 influx = InfluxDBClient('bang6', 9060, 'root', 'root', 'main') 40 influx = InfluxDBClient('bang6', 9060, 'root', 'root', 'main')
38 41
42 os.environ['DISPLAY'] = ':0.0'
43
44 dpms = DPMS()
45 host = socket.gethostname()
46
39 def getMonitorState(): 47 def getMonitorState():
40 out = subprocess.check_output(['xset', 'q']) 48 level, enabled = dpms.Info()
41 for line in out.splitlines(): 49 return 'on' if level == DPMSModeOn else 'off'
42 line = line.strip()
43 if line == 'Monitor is On':
44 return 'on'
45 elif line in ['Monitor is Off', 'Monitor is in Suspend', 'Monitor is in Standby']:
46 return 'off'
47 raise NotImplementedError("no matching monitor line in xset output")
48 50
49 class Root(cyclone.web.RequestHandler): 51 class Root(cyclone.web.RequestHandler):
50 def get(self): 52 def get(self):
51 getMonitorState() # to make it fail if xset isn't working 53 getMonitorState() # to make it fail if xset isn't working
52 self.write(''' 54 self.write('''
64 subprocess.check_call(['xset', 'dpms', 'force', body]) 66 subprocess.check_call(['xset', 'dpms', 'force', body])
65 self.set_status(204) 67 self.set_status(204)
66 else: 68 else:
67 raise NotImplementedError("body must be 'on' or 'off'") 69 raise NotImplementedError("body must be 'on' or 'off'")
68 70
69
70 class Graph(cyclone.web.RequestHandler):
71 def get(self):
72 host = socket.gethostname()
73 g = StateGraph(ctx=DEV['dpms/%s' % host])
74 g.add((URIRef("http://bigasterisk.com/host/%s/monitor" % host),
75 ROOM['powerStateMeasured'],
76 ROOM[getMonitorState()]))
77
78 self.set_header('Content-type', 'application/x-trig')
79 self.write(g.asTrig())
80
81
82 class Poller(object): 71 class Poller(object):
83 def __init__(self): 72 def __init__(self):
84 self.lastSent = None 73 self.lastSent = None
85 self.lastSentTime = 0 74 self.lastSentTime = 0
86 task.LoopingCall(self.poll).start(5) 75 task.LoopingCall(self.poll).start(5)
87 76
88 def poll(self): 77 def poll(self):
89 now = int(time.time()) 78 now = int(time.time())
90 try: 79 state = getMonitorState()
91 state = getMonitorState() 80
92 except subprocess.CalledProcessError, e: 81 ctx=DEV['dpms/%s' % host]
93 print repr(e) 82 masterGraph.patchObject(
94 os.abort() 83 ctx,
84 URIRef("http://bigasterisk.com/host/%s/monitor" % host),
85 ROOM['powerStateMeasured'],
86 ROOM[getMonitorState()])
87
95 if state != self.lastSent or (now > self.lastSentTime + 3600): 88 if state != self.lastSent or (now > self.lastSentTime + 3600):
96 influx.write_points([ 89 influx.write_points([
97 {'measurement': 'power', 90 {'measurement': 'power',
98 'tags': {'device': '%sMonitor' % socket.gethostname()}, 91 'tags': {'device': '%sMonitor' % host},
99 'fields': {'value': 1 if state == 'on' else 0}, 92 'fields': {'value': 1 if state == 'on' else 0},
100 'time': now 93 'time': now
101 }], time_precision='s') 94 }], time_precision='s')
102 95
103 self.lastSent = state 96 self.lastSent = state
104 self.lastSentTime = now 97 self.lastSentTime = now
105 98
106 setDisplayToLocalX() 99 masterGraph = PatchableGraph()
107 poller = Poller() 100 poller = Poller()
108 101
109 reactor.listenTCP(9095, cyclone.web.Application([ 102 reactor.listenTCP(9095, cyclone.web.Application([
110 (r'/', Root), 103 (r'/', Root),
111 (r'/monitor', Monitor), 104 (r'/monitor', Monitor),
112 (r'/graph', Graph), 105 (r'/graph', CycloneGraphHandler, {'masterGraph': masterGraph}),
106 (r'/graph/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}),
113 ]), interface='::') 107 ]), interface='::')
114 108
115 reactor.run() 109 reactor.run()
116 110
117 111