class ReceivingProtocol(LineReceiver): log = Log().buildLogger() def __init__(self, factory): self.factory = factory def connectionMade(self): self.log.info("connected") def connectionLost(self, reason): """ alert the factory to a lost connection """ self.factory._protocols.remove(self) self.log.info("connection lost: " + str(reason)) def lineReceived(self, line): if (line == 'CONNECT OK'): return self.produce(line) @inlineCallbacks def produce(self, data): datum = yield self.convertToDatum(data) yield self.factory.consume(datum) @inlineCallbacks def convertToDatum(self, strDatum): reading = yield defer.execute(dto.RawSensorReadingDTO.json_deserialize, strDatum) returnValue(reading)
class NRFProtocolFactory(Factory): log = Log().buildLogger() def __init__(self): self._protocols = [] def buildProtocol(self, address): protocol = NRFProtocol(self) self._protocols.append(protocol) self.log.info("building a protocol for: " + str(address)) return protocol @inlineCallbacks def consume(self, datum): yield self.broadcast(datum) @inlineCallbacks def broadcast(self, datum): self.log.debug("broadcasting") results = yield [ p.sendLine(self.datumToString(datum).encode()) for p in self._protocols ] returnValue(results) def datumToString(self, datum): msg = json.dumps(datum, default=lambda d: d.json_serialize()) return str(msg).replace(" ", "")
class SensorDataClientProtocol(WebSocketClientProtocol): log = Log().buildLogger() def __init__(self, factory): WebSocketClientProtocol.__init__(self) self.factory=factory def onOpen(self): self.log.info("connection successful") def onMessage(self, payload, isBinary): if not isBinary: self.log.info("Text message received");
class ReceivingProtocolFactory(ReconnectingClientFactory, ClientFactory): log = Log().buildLogger() def __init__(self): self._protocols = [] self._consumers = [] def buildProtocol(self, address): protocol = ReceivingProtocol(self) self._protocols.append(protocol) self.log.info("building a protocol for: " + str(address)) return protocol def startedConnecting(self, connector): self.log.info('Started to connect.') def clientConnectionLost(self, connector, reason): self.log.info('Lost connection. Reason: {}'.format(reason)) ReconnectingClientFactory.clientConnectionLost(self, connector, reason) def clientConnectionFailed(self, connector, reason): self.log.info('Connection failed. Reason: {}'.format(reason)) ReconnectingClientFactory.clientConnectionFailed( self, connector, reason) @inlineCallbacks def consume(self, datum): self.log.debug("consuming new data") results = yield self.produce(datum) returnValue(results) @inlineCallbacks def produce(self, datum): results = yield [c.consume(datum) for c in self._consumers] returnValue(results) def addConsumer(self, consumer): if consumer is not None: self.log.info("added a consumer: " + str(consumer.__class__)) self._consumers.append(consumer) else: log.warn("can't add a None consumer") def removeConsumer(self, consumer): if consumer in self._consumers: self._consumers.remove(consumer) log.info("removed a consumer: " + str(consumer.__class__))
class NRFProtocol(LineReceiver): log = Log().buildLogger() def __init__(self, factory): self.factory = factory def connectionMade(self): self.log.info("connected") self.sendLine("CONNECT OK".encode()) def connectionLost(self, reason): """ alert the factory to a lost connection """ self.factory._protocols.remove(self) self.log.info("connection lost: " + str(reason)) def lineReceived(self): """ this can be expanded as new features are added """ pass
class SensorDataClientFactory(ReconnectingClientFactory, WebSocketClientFactory): log = Log().buildLogger() def __init__(self, url): WebSocketClientFactory.__init__(self, url) self._protocols=[] protocol = SensorDataClientProtocol # http://twistedmatrix.com/documents/current/api/twisted.internet.protocol.ReconnectingClientFactory.html # maxDelay = 10 maxRetries = 5 def startedConnecting(self, connector): self.log.info('Started to connect.') def clientConnectionLost(self, connector, reason): self.log.info('Lost connection. Reason: {}'.format(reason)) ReconnectingClientFactory.clientConnectionLost(self, connector, reason) def clientConnectionFailed(self, connector, reason): self.log.info('Connection failed. Reason: {}'.format(reason)) ReconnectingClientFactory.clientConnectionFailed(self, connector, reason) def buildProtocol(self, address): protocol = SensorDataClientProtocol(self) self._protocols.append(protocol) self.log.info("building a protocol for: " + str(address)) return protocol @inlineCallbacks def consume(self, datum): yield self.broadcast(datum) @inlineCallbacks def broadcast(self, datum): self.log.debug("broadcasting") results = yield [p.sendMessage(self.datumToString(datum)) for p in self._protocols] returnValue(results) def datumToString(self, datum): msg = json.dumps(datum, default=lambda d: d.json_serialize()) return str(msg).replace(" ", "")
class NRF24Radio(NRF24): log = Log().buildLogger() IRQ_PIN = 19 def __init__(self): self._gpio = GPIO.get_platform_gpio() pipes = [ [0xE8, 0xE8, 0xF0, 0xF0, 0xE1], # writing address [0xF0, 0xF0, 0xF0, 0xF0, 0xE1] ] # reading address - sensors write to this self._gpio.setup(NRF24Radio.IRQ_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP) self._gpio.add_event_detect(NRF24Radio.IRQ_PIN, GPIO.FALLING) super(NRF24Radio, self).__init__() self.begin(0, 17) self.setPayloadSize(32) self.setChannel(0x76) self.setDataRate(NRF24.BR_1MBPS) self.setPALevel(NRF24.PA_MIN) self.setAutoAck(True) self.enableDynamicPayloads() self.enableAckPayload() self.openReadingPipe(1, pipes[1]) self.printDetails() def listen(self): self.startListening() def irqTriggered(self): return not self._gpio.event_detected(NRF24Radio.IRQ_PIN) def irqCallback(self, callback): self._gpio.add_event_callback(NRF24Radio.IRQ_PIN, callback) def readMessageToBuffer(self): receivedMessage = [] #self.print_status(self.get_status()) self.read(receivedMessage, self.getDynamicPayloadSize()) return receivedMessage
class SensorDataCollector(object): _log = Log().buildLogger() def __init__(self, radio): self._radio = radio self._consumers = [] @inlineCallbacks def listenForData(self): self._log.info("listenForData start") results = [] while self._radio.available(0): self._log.info("radio is available - processing") buffer = self._radio.readMessageToBuffer() rd = RawSensorReadingDTO(buffer, time.time()) results.append(self.produce(rd)) self._log.info("listenForData end") yield defer.gatherResults(results, consumeErrors=True) @inlineCallbacks def produce(self, data): consumerDeferreds = [x.consume(data) for x in self._consumers] results = yield defer.gatherResults(consumerDeferreds, consumeErrors=True) returnValue(results) def addConsumer(self, consumer): if consumer is not None: self._consumers.append(consumer) else: log.warn("can't add a None consumer") def removeConsumer(self, consumer): if consumer in self._consumers: self._consumers.remove(consumer)
import threading, queue from sb import util, radio, collector, processor from sb.radio import NRF24Radio from sb.collector import SensorDataCollector from sb.processor import SensorDataProcessor, WebServiceProcessor, DatabaseProcessor from twisted.internet import reactor, task from sb.util import Log globalLog = Log().buildLogger() #handle shutting down all the things def shutdown(radio): radio.end() globalLog.info("Finished shutting down the radio and GPIO.") if __name__ == "__main__": globalLog.info("Startin up NRF24 radio") radio = NRF24Radio() radio.listen() collector = SensorDataCollector(radio) globalLog.info("Collector created") processor = SensorDataProcessor() processor.addConsumer(WebServiceProcessor()) processor.addConsumer(DatabaseProcessor()) collector.addConsumer(processor)
class UtilTests(unittest.TestCase): log = Log().buildLogger() def test_convertToDict(self): dtoDict = convertToDict(SimpleDTO()) self.assertEquals(dtoDict, {'a': 'a', 'c': 'c', 'b': 'b'})
class FakeProcessor(object): log = Log().buildLogger() @inlineCallbacks def consume(self, resultingData): yield defer.execute(str, resultingData)
def buildRawSensorReadingDTOs(self, q, count=5): log = Log().buildLogger() func = lambda ord: q.put(RawSensorReadingDTO(ord, time.time())) builder.buildRangedOrdLists(func, 10000, 4, 2, 86)