Mercurial > code > home > repos > homeauto
changeset 1304:b686b989cf61
rm old pi kiosk thing that displayed calendars and stuff. maybe a thermostat knob. py server; knockout web page.
Ignore-this: 30d76ed408ccc9bfd2acefdd351fe8f9
darcs-hash:f834c3bfabf6513abac14742b3cbfb86faaec2bf
author | drewp <drewp@bigasterisk.com> |
---|---|
date | Sun, 21 Apr 2019 03:01:36 -0700 |
parents | f97e060d860c |
children | 965397a2648a |
files | service/wallscreen/gui.js service/wallscreen/index.html service/wallscreen/pydeps service/wallscreen/wallscreen.py service/wallscreen/websocket.js |
diffstat | 5 files changed, 0 insertions(+), 447 deletions(-) [+] |
line wrap: on
line diff
--- a/service/wallscreen/gui.js Sun Apr 21 02:57:17 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -var reloadData; -$(function () { - - setTimeout(function () { - window.resizeTo(702,480); - }, 10000); - - var model = { - requestedF: ko.observable(), - tasks: ko.observableArray([]), - events: ko.observableArray([]), - isToday: function (ev) { - var today = moment().format("YYYY-MM-DD"); - return ev.date == today; - }, - mapPersonData: ko.observable(), - }; - reloadData = function() { - $.getJSON("content", function (data) { - model.tasks(data.tasks); - model.events(data.events); - }); - } - setInterval(reloadData, 30*60*1000); - reloadData(); - - reloadMap = function () { - $.getJSON("content/map", function (data) { - var personData = []; - data.pts.forEach(function (pt) { - // this is in another config but not yet in the graph - var initial = pt.who.split("#")[1].substr(0, 1).toUpperCase(); - pt.initial = initial; - pt.topFrac = initial == 'K' ? 0 : .5; - personData.push(pt); - }); - model.mapPersonData(personData); - }); - }; - setInterval(reloadMap, 2*60*1000); - reloadMap(); - - function onMessage(d) { - if (d.tempF) { - model.requestedF(d.tempF); - } - } - reconnectingWebSocket("ws://bang.bigasterisk.com:9102/live", onMessage); - - ko.applyBindings(model); - - if (navigator.userAgent == "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:18.0) Gecko/18.0 Firefox/18.0") { - $(".rot").removeClass("rot"); - } - - function updateClock() { - var now = moment(); - var s = (new Date()).toLocaleTimeString(); - $("#clock").html( - "<div>"+now.format("dddd")+"</div>"+ - "<div>"+now.format("MMM Do")+"</div>"+ - "<div>"+now.format("HH:mm")+"</div>" - ) - } - setInterval(updateClock, 20000) - updateClock(); -});
--- a/service/wallscreen/index.html Sun Apr 21 02:57:17 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,202 +0,0 @@ -<!DOCTYPE html> -<html> - <head> - <meta charset='utf-8'> - <title>wallscreen</title> - <link href='http://fonts.googleapis.com/css?family=Yanone+Kaffeesatz:400' rel='stylesheet' type='text/css'></link> - <style type="text/css" media="all"> - /* <![CDATA[ */ - body { - background: black; - margin: 0; - } - p, ul { - margin: 0; - } - #edge { - position: absolute; - left: 14px; - top: 11px; - width: 463px; - height: 680px; - - background: black; - color: gray; - font-size: 30px; - line-height: 25px; - font-family: 'Yanone Kaffeesatz', sans-serif; - overflow: hidden; - } - - #edge.rot { - left: 113px; - top: -101px; - transform: rotate(90deg); - width: 463px; - height: 680px; - } - - @media screen and (-webkit-min-device-pixel-ratio:0) { - #edge { border: 1px solid red; } - } - - #clock { - bottom: 25px; - color: #4E8B4E; - font-size: 56px; - line-height: 63px; - position: absolute; - right: 5px; - text-align: right; - width: 134px; - } - - #todo { - width: 70%; - height: 60%; - overflow: hidden; - } - #todo h1 { - - } - .fg2 { - color: #2a2aa8; - } - .depth0 { padding-left: 0px; color: #fff; background: #1f2324} - .depth1 { padding-left: 20px; color: #777; } - .depth2 { padding-left: 40px; color: #3c3535; } - .depth3 { padding-left: 60px; color: #221e1e; } - - #events { - width: 70%; - height: 25%; - overflow: hidden; - } - #events > ul > li { - list-style: none; - margin-left: -26px; - } - #events h2 { - margin: 0; - padding: 0; - font-weight: normal; - font-size: 100%; - padding-left: 27px; - background: url(static/Free%20Blockie%20Set/Blue%20Glass/PNG%2024/calendar.png) no-repeat; - - } - - #events li.today h2 { - background: url(static/Free%20Blockie%20Set/Golden/PNG%2024/calendar.png) no-repeat; - - } - li.timeEvent { - list-style: none; - margin-left: -26px; - padding-left: 27px; - background: url(static/Free%20Blockie%20Set/Blue%20Glass/PNG%2024/clock.png) no-repeat; - } - - .today .timeEvent { - background: url(static/Free%20Blockie%20Set/Golden/PNG%2024/clock.png) no-repeat; - - } - h2 .dayName { - color: #666688; - font-size: 70%; - } - - #events > ul > li { - padding: 4px; - } - #events > li.today { - background: #432; - color: white; - } -#map { -height: 8%; -width: 70%; -overflow: hidden; -background: #111; -position: relative; -} - -#thermostat { -position: absolute; -left: 8px; -top: 640px; -} -#status { - color: red; - left: 100px; - position: absolute; - top: 100px; -} - -#map span.person { - position: absolute; - display: inline-block; - border-radius: 10px; - border: 1px solid gray; - background: rgba(21, 26, 21, 0.55); - width: 1em; - height: 1em; - text-align: center; -} - /* ]]> */ - </style> - - </head> - <body> - <div id="edge" class="rot"> - <div id="clock">..:..</div> - - <div id="todo"> - <p>Todo list:</p> - <ul data-bind="foreach: tasks"> - <li data-bind="attr: {class: ('depth'+depth+' '+(mark || ''))}"> - <span data-bind="text: content"></span> - </li> - </ul> - </div> - - <div id="events"> - <p>Calendar:</p> - <ul data-bind="foreach: events"> - <li data-bind="css: {today: $root.isToday($data)}"> - <h2> - <span data-bind="text: date"></span> - <span class="dayName" data-bind="text: weekdayName"></span> - </h2> - <ul> - <!-- ko foreach: dayEvents --> - <li><span data-bind="text: title"></span></li> - <!-- /ko --> - <!-- ko foreach: timeEvents --> - <li class="timeEvent"><span class="time" data-bind="text: time"></span> <span data-bind="text: title"></span></li> - <!-- /ko --> - </ul> - </li> - </ul> - </div> - <div id="map"> - <span class="place">⌂</span> - <!-- ko foreach: mapPersonData --> - <span class="person" data-bind="text: initial, style: {left: (frac*100+'%'), top: (topFrac*100+'%')}"></span> - <!-- /ko --> - </div> - <div id="thermostat"> - Thermostat at <span style="color: #FAB1FA;" data-bind="text: requestedF"></span>. Use knob to adjust. - </div> - <div id="status"></div> - - </div> - - <script src="//bigasterisk.com/lib/jquery-2.0.3.min.js"></script> - <script src="//bigasterisk.com/lib/underscore-1.5.2.min.js"></script> - <script src="//bigasterisk.com/lib/knockout-2.3.0.js"></script> - <script src="//bigasterisk.com/lib/moment.min.js"></script> - <script src="websocket.js"></script> - <script src="gui.js"></script> - </body> -</html>
--- a/service/wallscreen/pydeps Sun Apr 21 02:57:17 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -Automat==0.7.0 -cffi==1.11.5 -cyclone==1.0rc15 -enum34==1.1.6 -html5lib==1.0b3 -http-parser==0.8.3 -hyperlink==18.0.0 -idna==2.7 -incremental==17.5.0 -ipaddress==1.0.22 -isodate==0.4.9 -pycparser==2.18 -PyHamcrest==1.9.0 -pyOpenSSL==18.0.0 -pyparsing==1.5.7 -python-dateutil==2.1 -rdflib==4.0.1 -requests==2.9.1 -restkit==4.2.2 -SPARQLWrapper==1.5.2 -treq==15.1.0 -Twisted==18.7.0 -
--- a/service/wallscreen/wallscreen.py Sun Apr 21 02:57:17 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,135 +0,0 @@ -""" -for raspberry pi screen. - B2G_HOMESCREEN=http://10.1.0.1:9102 b2g/b2g --screen=700x480 -and then fix the window with this: - echo "window.resizeTo(702,480)" | nc localhost 9999 -""" -import json, sys, time -from dateutil.parser import parse -from twisted.internet import reactor, task -from twisted.internet.defer import inlineCallbacks -import cyclone.web, cyclone.httpclient, cyclone.websocket -from rdflib import Graph, ConjunctiveGraph, URIRef, Namespace, Literal, RDF - -sys.path.append("../../lib") -from logsetup import log -from cycloneerr import PrettyErrorHandler - -sys.path.append("../reasoning") -from rdflibtrig import addTrig - -CV = Namespace("http://bigasterisk.com/checkvist/v1#") -EV = Namespace("http://bigasterisk.com/event#") -MAP = Namespace("http://bigasterisk.com/map#") - -class Content(PrettyErrorHandler, cyclone.web.RequestHandler): - def get(self): - out = [] - if 1: - g = Graph() - g.parse("http://bang:9103/graph", format="n3") - - tasks = [] # (pos, task) - for t in g.subjects(RDF.type, CV.OpenTask): - if (None, CV.child, t) in g: - continue - tasks.append((g.value(t, CV.position), t)) - tasks.sort() - - def appendTree(t, depth): - out.append(dict( - uri=t, - depth=depth, - mark=g.value(t, CV.mark), - content=g.value(t, CV.content), - )) - for sub in g.objects(t, CV.child): - if (sub, RDF.type, CV.OpenTask) not in g: - continue - appendTree(sub, depth+1) - - for pos, t in tasks[:10]: - appendTree(t, depth=0) - - events = [] # [{'date':'yyyy-mm-dd', 'dayEvents':[], 'timeEvents':[]}] - g = Graph() - g.parse("http://bang:9105/events?days=3", format='n3') - byDay = {} - for ev in g.subjects(RDF.type, EV.Event): - start = g.value(ev, EV['start']) - s = parse(start) - d = s.date().isoformat() - byDay.setdefault(d, {'dayEvents':[], - 'timeEvents':[]})[ - 'timeEvents' if 'T' in start else 'dayEvents'].append({ - 'title' : g.value(ev, EV['title']), - 'start' : start, - 'date' : s.date().isoformat(), - 'time' : s.time().isoformat()[:-3], - }) - for k,v in sorted(byDay.items(), key=lambda (k,v): k): - d = {'date':k, 'weekdayName':parse(k).strftime("%A")} - d.update(v) - d['dayEvents'].sort(key=lambda ev: ev['title']) - d['timeEvents'].sort(key=lambda ev: ev['start']) - events.append(d) - - self.write(json.dumps({'tasks':out, 'events' : events})) - -class ContentMap(PrettyErrorHandler, cyclone.web.RequestHandler): - def get(self): - g = ConjunctiveGraph() - addTrig(g, "http://bang:9099/graph") - maxMeters = 65000 - pts = [] - print "loaded", len(g) - for s,p,o in g.triples((None, MAP['distanceToHomeM'], None)): - pts.append(dict(who=s, - frac=float(o) / maxMeters, - distanceToHomeM=o, - displayMilesDistance="%.1f miles" % - (float(o) * 0.000621371))) - self.write(json.dumps({'pts': pts})) - -@inlineCallbacks -def pushThermostat(): - f = json.loads((yield cyclone.httpclient.fetch("http://bang:10001/requestedTemperature")).body) - [c.sendMessage(f) for c in liveClients] - -class RefreshTemperature(PrettyErrorHandler, cyclone.web.RequestHandler): - def post(self): - return pushThermostat() - -liveClients = set() - -class Live(cyclone.websocket.WebSocketHandler): - def connectionMade(self, *args, **kwargs): - log.info("websocket opened") - liveClients.add(self) - - def connectionLost(self, reason): - log.info("websocket closed") - liveClients.remove(self) - - def messageReceived(self, message): - log.info("got message %s" % message) - self.sendMessage(message) - -if __name__ == '__main__': - from twisted.python import log as twlog - #twlog.startLogging(sys.stdout) - - task.LoopingCall(pushThermostat).start(1) - - port = 9102 - reactor.listenTCP(port, cyclone.web.Application(handlers=[ - (r'/content', Content), - (r'/content/map', ContentMap), - (r'/live', Live), - (r'/refreshTemperature', RefreshTemperature), - (r'/(.*)', cyclone.web.StaticFileHandler, - {"path" : ".", # security hole- serves this dir too - "default_filename" : "index.html"}), - ])) - log.info("serving on %s" % port) - reactor.run()
--- a/service/wallscreen/websocket.js Sun Apr 21 02:57:17 2019 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,20 +0,0 @@ -// from the light9/rdfdb one - -function reconnectingWebSocket(url, onMessage) { - var pong = 0; - function connect() { - var ws = new WebSocket(url); - - ws.onopen = function() { $("#status").text(""); }; - ws.onerror = function(e) { $("#status").text("error: "+e); }; - ws.onclose = function() { - pong = 1 - pong; - $("#status").text("disconnected (retrying "+(pong ? "😼":"😺")+")"); - setTimeout(connect, 2000); - }; - ws.onmessage = function (evt) { - onMessage(JSON.parse(evt.data)); - }; - } - connect(); -}