From 35bcf0e3f587da6c72e5cc140bc89c6681cb1450 Mon Sep 17 00:00:00 2001 From: scott francis Date: Fri, 17 Jul 2020 16:29:04 -0700 Subject: [PATCH] restore serial port and reduce non-CSV output to one state output per time cycle --- PentairProtocol.py | 4 ++-- README.md | 6 ++++++ pentair-control.py | 42 ++++++++++++++++++++++++++++++++++++++---- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/PentairProtocol.py b/PentairProtocol.py index 4cd6f40..2e65c56 100644 --- a/PentairProtocol.py +++ b/PentairProtocol.py @@ -125,7 +125,7 @@ def __init__(self, body): self.status['delay'] = self.body[12] & self.DELAY self.status['waterTemp'] = self.body[14] # repeated in body[15] - self.status['waterTemp2'] = self.body[15] + self.status['spaTemp'] = self.body[15] self.status['airTemp'] = self.body[18] self.status['solarTemp'] = self.body[19] @@ -202,7 +202,7 @@ def __init__(self, body): try: # 8 unused bytes... probably solar and other features I don't have (self.status['waterTemp'], - self.status['waterTemp2'], + self.status['spaTemp'], self.status['airTemp'], self.status['poolSetTemp'], self.status['spaSetTemp']) = struct.unpack("bbbbbxxxxxxxx", self.body) diff --git a/README.md b/README.md index 54aeb4f..71c923b 100644 --- a/README.md +++ b/README.md @@ -6,12 +6,18 @@ While this project targets AWS IoT / Greengrass integration, the components shou * Current Status: Framework for capturing messages on the 485 bus and decoding payloads works. Payload decoders built for most common messages I see on my system Useful for understanding and decoding live protocol or collecting traffic samples. +* has a 'CSV' mode that can output the frame fields (see below) and the parsed payload +* can read from file (reply test or cached or forwarded port -- also described below) or serial port +* aggregates a 'state' by updating a dict so keys can come from multiple payloads +* Uses an Observer/Obervable pipeline for flexible processing _TODO_ 1. Integrate latest AWS IoT Device SDK to publish messages to Greengrass (this will also facilitate debug) 2. Migrate protocol decoding to Greengrass Lambdas 3. Build coherent model for 'the pool' from collected messages and maintain model in Device Shadow 4. Implement commands: SPA On, Pool On, All Off, Heat Pool, Heat Spa, Heat Off +5. clean out crufty and unreacahble code +6. refactor many classes to be more 'generic' ### Purpose diff --git a/pentair-control.py b/pentair-control.py index 71bfcf9..d16069e 100755 --- a/pentair-control.py +++ b/pentair-control.py @@ -46,6 +46,23 @@ def append(self, newElements): self.notifyObservers(self.elements) self.clear() +# an Observable wrapped dict +class ObservableDict(Observable): + def __init__(self): + super().__init__() + self.clear() + + def clear(self): + self.dict = {} + + def append(self, newDict): + if len(newDict) > 0: + self.dict.update(newDict) + + def getDict(self): + return self.dict + + # takes a stream on #update and writes it to the messages object, using messages#append class MessageParser(Observer): def __init__(self, separator, messages): @@ -85,6 +102,17 @@ def __init__(self, payloads): def update(self, frames): self.payloads.append(list(map(self.protocol.parsePayload, frames))) +class stateAggregator(Observer): + def __init__(self, state): + super().__init__() + self.state = state + + def update(self, parsedFrames): + for p in parsedFrames: + if 'state' in p: + self.state.append(p['state']) + + class CSVOutput(Observer): def __init__(self): super().__init__() @@ -119,14 +147,14 @@ def update(self, objects): parser.add_argument("-i", "--inputfile", action="store", required=False, dest="inFile", default="", help="input file with raw protocol stream") # serial port args -# parser.add_argument("-p", "--port", action="store", required=True, dest="port", default="/dev/ttyS0", help="Serial Port Device") +parser.add_argument("-p", "--port", action="store", required=True, dest="port", default="/dev/ttyS0", help="Serial Port Device") parser.add_argument("-t", "--timeout", action="store", required=True, dest="timeout", default="0.5", help="Timeout to wait for events") # # Output Options # -parser.add_argument("-c", "--csv", action="store", required=False, dest="csv", default=False, help="print every frame in csv, don't parse") +parser.add_argument("-c", "--csv", action="store", required=False, dest="csv", default='False', help="print every frame in csv, don't parse") # mqtt publish... args = parser.parse_args() @@ -143,7 +171,8 @@ def update(self, objects): streamData = ObservableString() messages = ObservableArray() frames = ObservableArray() -# payloads = ObservableArray() +state = ObservableDict() + if len(inFile) > 0: print(f'using {inFile} as source') @@ -165,6 +194,10 @@ def update(self, objects): frameParser = FrameParser(frames) messages.addObserver(frameParser) +state = ObservableDict() +stateAggregator = stateAggregator(state) +frames.addObserver(stateAggregator) + if csv: output = CSVOutput() frames.addObserver(output) @@ -175,8 +208,9 @@ def do_something(): if not connection.isOpen(): connection.open() + state.clear() streamData.append(connection.listen()) - + print(json.dumps(state.getDict())) def run(): if not connection.isOpen():