Mercurial > code > home > repos > homeauto
changeset 1491:6cd9341f0a28
xidle rewrite for docker, py3
Ignore-this: a866446f3f42069092dc40b48f12d46b
darcs-hash:67026da0e635b31e2cec59037397b99b0ce7c4ac
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Wed, 29 Jan 2020 01:02:06 -0800 |
parents | 455b1b80516e |
children | 7c7415cfbc02 |
files | service/xidle/Dockerfile service/xidle/Dockerfile.pi service/xidle/makefile service/xidle/requirements.txt service/xidle/tasks.py service/xidle/xidle.py |
diffstat | 6 files changed, 129 insertions(+), 63 deletions(-) [+] |
line wrap: on
line diff
--- a/service/xidle/Dockerfile Thu Jan 23 21:00:47 2020 -0800 +++ b/service/xidle/Dockerfile Wed Jan 29 01:02:06 2020 -0800 @@ -3,13 +3,12 @@ RUN apt-get install --yes libxss-dev COPY requirements.txt ./ -RUN pip install -r requirements.txt - -ADD https://projects.bigasterisk.com/rdfdb/more.tgz ./ -RUN tar xvzf more.tgz +RUN pip3 install --index-url https://projects.bigasterisk.com/ --extra-index-url https://pypi.org/simple -r requirements.txt +# not sure why this doesn't work from inside requirements.txt +RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip?v3' COPY *.py ./ EXPOSE 9107 -CMD [ "python", "./xidle.py" ] +CMD [ "python3", "./xidle.py" ]
--- a/service/xidle/Dockerfile.pi Thu Jan 23 21:00:47 2020 -0800 +++ b/service/xidle/Dockerfile.pi Wed Jan 29 01:02:06 2020 -0800 @@ -3,13 +3,12 @@ RUN apt-get install --yes libxss-dev COPY requirements.txt ./ -RUN pip install -r requirements.txt - -ADD https://projects.bigasterisk.com/rdfdb/more.tgz ./ -RUN tar xvzf more.tgz +RUN pip3 install --index-url https://projects.bigasterisk.com/ --extra-index-url https://pypi.org/simple -r requirements.txt +# not sure why this doesn't work from inside requirements.txt +RUN pip3 install -U 'https://github.com/drewp/cyclone/archive/python3.zip?v3' COPY *.py ./ EXPOSE 9107 -CMD [ "python", "./xidle.py" ] +CMD [ "python3", "./xidle.py" ]
--- a/service/xidle/makefile Thu Jan 23 21:00:47 2020 -0800 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,18 +0,0 @@ -build_image: - (cd /my/proj/homeauto/lib; tar czf /my/site/projects/rdfdb/more.tgz *.py) - docker build --network=host -t bang6:5000/xidle_x86:latest . - docker push bang6:5000/xidle_x86:latest - -build_image_pi: - (cd /my/proj/homeauto/lib; tar czf /my/site/projects/rdfdb/more.tgz *.py) - docker build --file Dockerfile.pi --network=host -t bang6:5000/xidle_pi:latest . - docker push bang6:5000/xidle_pi:latest - -shell: - docker run --rm -it --cap-add SYS_PTRACE -v /tmp/.X11-unix/:/tmp/.X11-unix/ -v /home/drewp/.Xauthority:/root/.Xauthority --net=host bang6:5000/xidle_x86:latest /bin/sh - -local_run: - docker run --rm -it -v /tmp/.X11-unix/:/tmp/.X11-unix/ -v /home/drewp/.Xauthority:/root/.Xauthority -p 9107:9107 --net=host bang6:5000/xidle_x86:latest python ./xidle.py -v - -redeploy: build_image build_image_pi - sudo /my/proj/ansible/playbook -t homeauto_xidle
--- a/service/xidle/requirements.txt Thu Jan 23 21:00:47 2020 -0800 +++ b/service/xidle/requirements.txt Wed Jan 29 01:02:06 2020 -0800 @@ -1,9 +1,11 @@ -python-dateutil -rdflib==4.2.2 - +cyclone influxdb==4.1.1 -cyclone +python-dateutil +rdflib-jsonld==0.3 +rdflib==4.2.2 service_identity -actmon -https://projects.bigasterisk.com/rdfdb/rdfdb-0.3.0.tar.gz -rdflib-jsonld==0.3 + +git+http://github.com/drewp/scales.git@448d59fb491b7631877528e7695a93553bfaaa93#egg=scales +patchablegraph==0.7.0 +rdfdb==0.9.0 +standardservice==0.6.0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/service/xidle/tasks.py Wed Jan 29 01:02:06 2020 -0800 @@ -0,0 +1,33 @@ +from invoke import task +JOB = 'xidle' +PORT = 9107 +TAG_x86 = f'bang6:5000/{JOB.lower()}_x86:latest' +TAG_pi = f'bang6:5000/{JOB.lower()}_pi:latest' +ANSIBLE_TAG = 'homeauto_xidle' + +@task +def build_image_x86(ctx): + ctx.run(f'docker build --network=host -t {TAG_x86} .') +@task +def build_image_pi(ctx): + ctx.run(f'docker build --file Dockerfile.pi --network=host -t {TAG_pi} .') + +@task(pre=[build_image_x86]) +def push_image_x86(ctx): + ctx.run(f'docker push {TAG_x86}') +@task(pre=[build_image_pi]) +def push_image_pi(ctx): + ctx.run(f'docker push {TAG_pi}') + +@task(pre=[build_image_x86]) +def shell(ctx): + ctx.run(f'docker run --rm -it --cap-add SYS_PTRACE -v /tmp/.X11-unix/:/tmp/.X11-unix/ -v /home/drewp/.Xauthority:/root/.Xauthority --net=host {TAG_x86} /bin/bash', pty=True) + +@task(pre=[build_image_x86]) +def local_run(ctx): + ctx.run(f'docker run --rm -it -v /tmp/.X11-unix/:/tmp/.X11-unix/ -v /home/drewp/.Xauthority:/root/.Xauthority -p {PORT}:{PORT} -v /etc/resolv.conf:/etc/resolv.conf --net=host {TAG_x86} python3 xidle.py -v', pty=True) + +@task(pre=[push_image_x86, push_image_pi]) +def redeploy(ctx): + ctx.run(f'sudo /my/proj/ansible/playbook -t {ANSIBLE_TAG}') + #ctx.run(f'supervisorctl -s http://bang:9001/ restart {JOB}_{PORT}')
--- a/service/xidle/xidle.py Thu Jan 23 21:00:47 2020 -0800 +++ b/service/xidle/xidle.py Wed Jan 29 01:02:06 2020 -0800 @@ -1,5 +1,3 @@ -#!bin/python -from __future__ import division """ X server idle time is now available over http! @@ -8,60 +6,112 @@ xinput disable "HP Webcam HD-4110" """ - import time -import sys, socket, json, os +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 - -import actmon -# another option: http://thp.io/2007/09/x11-idle-time-and-focused-window-in.html +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/") -sys.path.append('../../lib') -from patchablegraph import PatchableGraph, CycloneGraphEventsHandler, CycloneGraphHandler - host = socket.gethostname() client = InfluxDBClient('bang6', 9060, 'root', 'root', 'main') os.environ['DISPLAY'] = ':0.0' -actmon.get_idle_time() # fail if we can't get the display or something +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): - actmon.get_idle_time() # fail if we can't get the display or something + 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. - <a href="graph">rdf graph</a> available.''' % host) - + + <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" : actmon.get_idle_time()})) - + self.write(json.dumps({"idleMs" : get_idle_time()})) + class Poller(object): def __init__(self): self.points = [] self.lastSent = None self.lastSentTime = 0 - task.LoopingCall(self.poll).start(5) - + self.lastGraphSent = None + self.lastGraphSentTime = 0 + task.LoopingCall(self.poll).start(1) + def poll(self): - ms = actmon.get_idle_time() + ms = get_idle_time() ctx = DEV['xidle/%s' % host] subj = URIRef("http://bigasterisk.com/host/%s/xidle" % host) - masterGraph.patchObject(ctx, subj, ROOM['idleTimeMs'], Literal(ms)) - masterGraph.patchObject(ctx, subj, ROOM['idleTimeMinutes'], - Literal(ms / 1000 / 60)) - 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"}, @@ -73,19 +123,20 @@ try: client.write_points(self.points, time_precision='s') except influxdb.exceptions.InfluxDBServerError as e: - print repr(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', CycloneGraphHandler, {'masterGraph': masterGraph}), - (r'/graph/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}), + (r'/graph/xidle', CycloneGraphHandler, {'masterGraph': masterGraph}), + (r'/graph/xidle/events', CycloneGraphEventsHandler, {'masterGraph': masterGraph}), ]), interface='::') reactor.run()