# HG changeset patch # User drewp # Date 1455273689 28800 # Node ID d2007482aec5190d473bdf968444f60050708aa7 # Parent e1693cc0b9928bfd25f8b49eeeb91b2ee786f9d2 start sending oneshot events from some devices Ignore-this: 2c98200e9bab1acca872f4cdcaf88e4d darcs-hash:b2f012ddfc31f4800c4c1c34ebb6243169b70a67 diff -r e1693cc0b992 -r d2007482aec5 service/arduinoNode/arduinoNode.py --- a/service/arduinoNode/arduinoNode.py Tue Feb 09 22:10:38 2016 -0800 +++ b/service/arduinoNode/arduinoNode.py Fri Feb 12 02:41:29 2016 -0800 @@ -8,6 +8,7 @@ import shutil, json import serial import cyclone.web +from cyclone.httpclient import fetch from rdflib import Graph, Namespace, URIRef, Literal, RDF, ConjunctiveGraph from rdflib.parser import StringInputSource from twisted.internet import reactor, task @@ -127,6 +128,11 @@ for i in self._polledDevs: now = time.time() new = i.readFromPoll(self.ser.read) + if isinstance(new, dict): # new style + oneshot = new['oneshot'] + new = new['latest'] + else: + oneshot = None prev = self._statementsFromInputs.get(i.uri, []) if new or prev: self._statementsFromInputs[i.uri] = new @@ -139,6 +145,8 @@ # fail since the '2' statement is gone) self.masterGraph.patch(Patch.fromDiff(inContext(prev, i.uri), inContext(new, i.uri))) + if oneshot: + self._sendOneshot(oneshot) self._lastPollTime[i.uri] = now #plus statements about succeeding or erroring on the last poll @@ -150,6 +158,15 @@ log.warn('poll took %.1f seconds' % elapsed) self._exportToGraphite() + def _sendOneshot(self, oneshot): + body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3()) + for s,p,o in oneshot)).encode('utf8') + bang6 = 'fcb8:4119:fb46:96f8:8b07:1260:0f50:fcfa' + fetch(method='POST', + url='http://[%s]:9071/oneShot' % bang6, + headers={'Content-Type': ['text/n3']}, postdata=body, + timeout=5) + def _exportToGraphite(self): # note this is writing way too often- graphite is storing at a lower res now = time.time() diff -r e1693cc0b992 -r d2007482aec5 service/arduinoNode/devices.py --- a/service/arduinoNode/devices.py Tue Feb 09 22:10:38 2016 -0800 +++ b/service/arduinoNode/devices.py Fri Feb 12 02:41:29 2016 -0800 @@ -177,6 +177,10 @@ @register class MotionSensorInput(DeviceType): deviceType = ROOM['MotionSensor'] + def __init__(self, graph, uri, pinNumber): + DeviceType.__init__(self, graph, uri, pinNumber) + self.lastRead = None + def generateSetupCode(self): return 'pinMode(%(pin)d, INPUT); digitalWrite(%(pin)d, LOW);' % { 'pin': self.pinNumber, @@ -192,12 +196,17 @@ if b not in 'yn': raise ValueError('unexpected response %r' % b) motion = b == 'y' - - return [ + + oneshot = [] + if self.lastRead is not None and motion != self.lastRead: + oneshot = [(self.uri, ROOM['sees'], ROOM['motionStart'])] + self.lastRead = motion + + return {'latest': [ (self.uri, ROOM['sees'], ROOM['motion'] if motion else ROOM['noMotion']), self.recentMotionStatement(motion), - ] + ], 'oneshot': oneshot} def recentMotionStatement(self, motion): if not hasattr(self, 'lastMotionTime'): diff -r e1693cc0b992 -r d2007482aec5 service/piNode/devices.py --- a/service/piNode/devices.py Tue Feb 09 22:10:38 2016 -0800 +++ b/service/piNode/devices.py Fri Feb 12 02:41:29 2016 -0800 @@ -122,11 +122,11 @@ def poll(self): motion = self.pi.read(17) - return [ + return {'latest': [ (self.uri, ROOM['sees'], ROOM['motion'] if motion else ROOM['noMotion']), self.recentMotionStatement(motion), - ] + ], 'oneshot': []} def recentMotionStatement(self, motion): if not hasattr(self, 'lastMotionTime'): @@ -257,14 +257,25 @@ log.debug("setup switch on %r", self.pinNumber) self.pi.set_mode(self.pinNumber, pigpio.INPUT) self.pi.set_pull_up_down(self.pinNumber, pigpio.PUD_UP) + self.lastClosed = None def poll(self): closed = not self.pi.read(self.pinNumber) - - return [ + + if self.lastClosed is not None and closed != self.lastClosed: + oneshot = [ + (self.uri, ROOM['buttonState'], + ROOM['press'] if closed else ROOM['release']), + ] + else: + oneshot = [] + self.lastClosed = closed + + return {'latest': [ (self.uri, ROOM['buttonState'], ROOM['pressed'] if closed else ROOM['notPressed']), - ] + ], + 'oneshot':oneshot} def watchPrefixes(self): return [ diff -r e1693cc0b992 -r d2007482aec5 service/piNode/piNode.py --- a/service/piNode/piNode.py Tue Feb 09 22:10:38 2016 -0800 +++ b/service/piNode/piNode.py Fri Feb 12 02:41:29 2016 -0800 @@ -1,6 +1,7 @@ from __future__ import division import sys, logging, socket, json, time, os import cyclone.web +from cyclone.httpclient import fetch from rdflib import Namespace, URIRef, Literal, Graph, RDF, ConjunctiveGraph from rdflib.parser import StringInputSource from twisted.internet import reactor, task @@ -72,7 +73,13 @@ self._lastPollTime.get(i.uri, 0) + i.pollPeriod > now): continue new = i.poll() + if isinstance(new, dict): # new style + oneshot = new['oneshot'] + new = new['latest'] + else: + oneshot = None prev = self._statementsFromInputs.get(i.uri, []) + if new or prev: self._statementsFromInputs[i.uri] = new # it's important that quads from different devices @@ -84,9 +91,21 @@ # fail since the '2' statement is gone) self.masterGraph.patch(Patch.fromDiff(inContext(prev, i.uri), inContext(new, i.uri))) + + if oneshot: + self._sendOneshot(oneshot) self._lastPollTime[i.uri] = now self._exportToGraphite() + def _sendOneshot(self, oneshot): + body = (' '.join('%s %s %s .' % (s.n3(), p.n3(), o.n3()) + for s,p,o in oneshot)).encode('utf8') + bang6 = 'fcb8:4119:fb46:96f8:8b07:1260:0f50:fcfa' + fetch(method='POST', + url='http://[%s]:9071/oneShot' % bang6, + headers={'Content-Type': ['text/n3']}, postdata=body, + timeout=5) + def _exportToGraphite(self): # note this is writing way too often- graphite is storing at a lower res now = time.time() diff -r e1693cc0b992 -r d2007482aec5 service/reasoning/reasoning.py --- a/service/reasoning/reasoning.py Tue Feb 09 22:10:38 2016 -0800 +++ b/service/reasoning/reasoning.py Fri Feb 12 02:41:29 2016 -0800 @@ -310,7 +310,7 @@ try: g = parseRdf(self.request.body, self.request.headers['content-type']) for s in g: - print "stmt", s + log.debug("oneshot stmt %r", s) if not len(g): log.warn("incoming oneshot graph had no statements: %r", self.request.body) return diff -r e1693cc0b992 -r d2007482aec5 service/reasoning/rules.n3 --- a/service/reasoning/rules.n3 Tue Feb 09 22:10:38 2016 -0800 +++ b/service/reasoning/rules.n3 Fri Feb 12 02:41:29 2016 -0800 @@ -129,12 +129,17 @@ :storageCeilingLedLong :brightness "1" . } . +{ :sees . } => { + :storageCeilingLedCross :brightness "1" . + :storageCeilingLedLong :brightness "1" . +} . + @prefix bed: . -{ bed:greenButton :buttonState :pressed } => { +{ bed:greenButton :buttonState :press } => { :headboardWhite :brightness 0 . } . -{ bed:redButton :buttonState :pressed } => { +{ bed:redButton :buttonState :press } => { :headboardWhite :brightness 0.04 . } . \ No newline at end of file