Mercurial > code > home > repos > homeauto
view service/xidle/xidle.py @ 1533:a598d2141587
more mqtt_to_rdf renames. bring in basic LitElement setup for the debug page
Ignore-this: 85e2ab49915e44b08219e537fab21870
darcs-hash:f2d312ec10bb4a33c501a24bd7d11a1f35673f25
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sat, 08 Feb 2020 04:02:22 -0800 |
parents | 6cd9341f0a28 |
children | 2500a3ee9102 |
line wrap: on
line source
""" X server idle time is now available over http! Note: HD-4110 webcams stop X from going idle by sending events constantly. Run this to fix: xinput disable "HP Webcam HD-4110" """ import time import socket, json, os from rdflib import Namespace, URIRef, Literal from influxdb import InfluxDBClient import influxdb.exceptions import cyclone.web from twisted.internet import reactor, task from standardservice.logsetup import log, verboseLogging from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler DEV = Namespace("http://projects.bigasterisk.com/device/") ROOM = Namespace("http://projects.bigasterisk.com/room/") host = socket.gethostname() client = InfluxDBClient('bang6', 9060, 'root', 'root', 'main') os.environ['DISPLAY'] = ':0.0' import pxss # another option: http://thp.io/2007/09/x11-idle-time-and-focused-window-in.html def get_idle_time(): return pxss.get_info().idle get_idle_time() # fail if we can't get the display or something class Root(cyclone.web.RequestHandler): def get(self): get_idle_time() # fail if we can't get the display or something self.set_header('content-type', 'text/html') self.write(''' <!doctype html> <html> <head> <title>xidle</title> <meta charset="utf-8" /> <script src="/lib/polymer/1.0.9/webcomponentsjs/webcomponents.min.js"></script> <script src="/lib/require/require-2.3.3.js"></script> <script src="/rdf/common_paths_and_ns.js"></script> <link rel="import" href="/rdf/streamed-graph.html"> <link rel="import" href="/lib/polymer/1.0.9/polymer/polymer.html"> <meta name="mobile-web-app-capable" content="yes"> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <template id="t" is="dom-bind"> Get the <a href="idle">X idle time</a> on %s. <streamed-graph url="graph/xidle/events" graph="{{graph}}"></streamed-graph> <div id="out"></div> <script type="module" src="/rdf/streamed_graph_view.js"></script> </template> <style> .served-resources { margin-top: 4em; border-top: 1px solid gray; padding-top: 1em; } .served-resources a { padding-right: 2em; } </style> <div class="served-resources"> <a href="stats/">/stats/</a> <a href="graph/dpms">/graph/dpms</a> <a href="graph/dpms/events">/graph/dpms/events</a> <a href="idle">/idle</a> </div> </body> </html> ''' % host) class Idle(cyclone.web.RequestHandler): def get(self): self.set_header('Content-type', 'application/json') self.write(json.dumps({"idleMs" : get_idle_time()})) class Poller(object): def __init__(self): self.points = [] self.lastSent = None self.lastSentTime = 0 self.lastGraphSent = None self.lastGraphSentTime = 0 task.LoopingCall(self.poll).start(1) def poll(self): ms = get_idle_time() ctx = DEV['xidle/%s' % host] subj = URIRef("http://bigasterisk.com/host/%s/xidle" % host) lastMinActive = ms < 60 * 1000 now = int(time.time()) nextGraphUpdate = self.lastGraphSentTime + min(10, ms / 1000 / 2) if self.lastGraphSent != lastMinActive or now > nextGraphUpdate: masterGraph.patchObject(ctx, subj, ROOM['idleTimeMs'], Literal(ms)) masterGraph.patchObject(ctx, subj, ROOM['idleTimeMinutes'], Literal(round(ms / 1000 / 60, 2))) self.lastGraphSent = lastMinActive self.lastGraphSentTime = now if self.lastSent != lastMinActive or now > self.lastSentTime + 3600: self.points.append({"measurement": "presence", "tags": {"host": host, "sensor": "xidle"}, "fields": {"value": 1 if lastMinActive else 0}, "time": now}) self.lastSent = lastMinActive self.lastSentTime = now try: client.write_points(self.points, time_precision='s') except influxdb.exceptions.InfluxDBServerError as e: log.error(repr(e)) reactor.crash() self.points = [] verboseLogging(False) masterGraph = PatchableGraph() poller = Poller() reactor.listenTCP(9107, cyclone.web.Application([ (r'/', Root), (r'/idle', Idle), (r'/graph/xidle', CycloneGraphHandler, {'masterGraph': masterGraph}), (r'/graph/xidle/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}), ]), interface='::') reactor.run()