diff environment.py @ 0:3c1bc3bc5a6c

pull out of homeauto/ project, and add skaffold/pipenv
author drewp@bigasterisk.com
date Thu, 31 Mar 2022 22:03:43 -0700
parents
children 0f532eb91364
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/environment.py	Thu Mar 31 22:03:43 2022 -0700
@@ -0,0 +1,110 @@
+#!/usr/bin/python
+"""
+return some rdf about the environment, e.g. the current time,
+daytime/night, overall modes like 'maintenance mode', etc
+
+"""
+import datetime
+
+import cyclone.web
+from dateutil.relativedelta import FR, relativedelta
+from dateutil.tz import tzlocal
+from docopt import docopt
+from rdflib import Literal, Namespace
+from twisted.internet import defer, reactor, task
+
+from standardservice.logsetup import log, verboseLogging
+from patchablegraph import (CycloneGraphEventsHandler, CycloneGraphHandler, PatchableGraph)
+
+from patch_cyclone import patch_sse
+from rdfdoc import Doc
+from twilight import isWithinTwilight
+
+patch_sse()
+
+ROOM = Namespace("http://projects.bigasterisk.com/room/")
+DEV = Namespace("http://projects.bigasterisk.com/device/")
+
+# STATS = scales.collection(
+#     '/root',
+#     scales.PmfStat('update'),
+# )
+
+
+# see pending fix in patchablegraph.py
+class CycloneGraphEventsHandlerWithCors(CycloneGraphEventsHandler):
+
+    def __init__(self, application, request, masterGraph, allowOrigins=None):
+        super().__init__(application, request, masterGraph)
+        self.allowOrigins = allowOrigins or []
+
+    def flush(self):
+        origin = self.request.headers.get('origin', None)
+        if origin and origin in self.allowOrigins:
+            self.set_header(b"Access-Control-Allow-Origin", origin.encode('utf8'))
+            self.set_header(b"Access-Control-Allow-Credentials", b"true")
+        return CycloneGraphEventsHandler.flush(self)
+
+
+# @STATS.update.time()
+def update(masterGraph):
+    stmt = lambda s, p, o: masterGraph.patchObject(ROOM.environment, s, p, o)
+
+    now = datetime.datetime.now(tzlocal())
+
+    stmt(DEV.environment, ROOM.localHour, Literal(now.hour))
+    stmt(DEV.environment, ROOM.localTimeToMinute, Literal(now.strftime("%H:%M")))
+
+    stmt(DEV.environment, ROOM.localTimeToSecond, Literal(now.strftime("%H:%M:%S")))
+
+    stmt(DEV.environment, ROOM.localDayOfWeek, Literal(now.strftime("%A")))
+    stmt(DEV.environment, ROOM.localMonthDay, Literal(now.strftime("%B %e")))
+    stmt(DEV.environment, ROOM.localDate, Literal(now.strftime("%Y-%m-%d")))
+
+    for offset in range(-12, 7):
+        d = now.date() + datetime.timedelta(days=offset)
+        if d == d + relativedelta(day=31, weekday=FR(-1)):
+            stmt(DEV.calendar, ROOM.daysToLastFridayOfMonth, Literal(offset))
+
+    stmt(DEV.calendar, ROOM.twilight, ROOM['withinTwilight'] if isWithinTwilight(now) else ROOM['daytime'])
+
+
+def main():
+    arg = docopt("""
+    Usage: environment.py [options]
+
+    -v                    Verbose
+    """)
+    verboseLogging(arg['-v'])
+
+    masterGraph = PatchableGraph()
+
+    class Application(cyclone.web.Application):
+
+        def __init__(self):
+            handlers = [
+                (r"/()", cyclone.web.StaticFileHandler, {
+                    "path": ".",
+                    "default_filename": "index.html"
+                }),
+                (r'/graph/environment', CycloneGraphHandler, {
+                    'masterGraph': masterGraph
+                }),
+                (r'/graph/environment/events', CycloneGraphEventsHandlerWithCors, {
+                    'masterGraph': masterGraph,
+                    'allowOrigins': ['http://localhost:8001'],
+                }),
+                (r'/doc', Doc),  # to be shared
+                # (r'/stats/(.*)', StatsHandler, {
+                #     'serverName': 'environment'
+                # }),
+            ]
+            cyclone.web.Application.__init__(self, handlers, masterGraph=masterGraph)
+
+    task.LoopingCall(update, masterGraph).start(1)
+    reactor.listenTCP(8080, Application())
+    reactor.run()
+
+
+if __name__ == '__main__':
+    main()