diff --git a/PentairProtocol.py b/PentairProtocol.py index 8395a00..4cd6f40 100644 --- a/PentairProtocol.py +++ b/PentairProtocol.py @@ -25,6 +25,8 @@ def dumpBody(self): def getStatus(self): + # if len(self.status) > 0: + # self.dump() return self.status # @@ -146,7 +148,7 @@ def __init__(self, body): self.status['pumpWatts'], self.status['pumpRPM'] ) = struct.unpack(">BBHH", self.body[1:9]) - print(f"read RPM {self.status['pumpRPM']} from:"); self.dumpBody() + # print(f"read RPM {self.status['pumpRPM']} from:"); self.dumpBody() # there are a lot more bytes... seem to be sequence number... except Exception as err: @@ -160,7 +162,6 @@ def __init__(self, body): try: if self.body[0] != 0xFF: print(f'unkown ping data: {body[0]:02X}') - except Exception as err: pass @@ -182,13 +183,13 @@ def __init__(self, body): class CommandPayload(Payload): def __init__(self, body): super().__init__(body) - print("Command Payload") + # print("Command Payload") self.dumpBody() try: - (self.status['pumpRPM'],) = struct.unpack(">H", self.body[-2:]) - print(f"read RPM {self.status['pumpRPM']} from:"); self.dumpBody() - + # (self.status['pumpRPM'],) = struct.unpack(">H", self.body[-2:]) + # print(f"read RPM {self.status['pumpRPM']} from:"); self.dumpBody() + pass except Exception as err: pass @@ -217,9 +218,9 @@ class PentairProtocol: def __init__(self): self.payloads = { - 0x00: { 0x01: CommandPayload, - 0x04: PingPayload, - 0x06: PumpStatus, + 0x00: { #0x01: CommandPayload, + #0x04: PingPayload, + #0x06: PumpStatus, 0x07: PumpPayload }, 0x24: { 0x02: StatusPayload, 0x05: DatePayload, @@ -255,6 +256,29 @@ def validFrame(self, f): return valid + # + # parsePayloadFromFrame + # + def parsePayloadFromFrame(self, frame): + state = {} + + try: + if frame['payloadLength'] != len(frame['payload']): + raise Exception + + payload = self.payloads[frame['type']][frame['command']](frame['payload']) + # self.state.update(payload.getStatus()) # just overwrite ... and get the latest + state = payload.getStatus() + # payload.dump() + + except Exception as err: + # print(err) + # print(",".join(list(map((lambda x: f'{x:02X}' if not isinstance(x, Iterable) else ' '.join(f'{b:02X}' for b in x) if len(x) > 0 else ''), list(frame.values()))))) + pass + + return state + + # # parseFrame # @@ -277,6 +301,8 @@ def parseFrame(self, f): parsed['payloadLength'] = f[5] parsed['payload'] = f[6:-2] + parsed['state'] = self.parsePayloadFromFrame(parsed) + except Exception as e: pass @@ -289,18 +315,18 @@ def parseEvents(self, events): if self.validFrame(e): frames.append(self.parseFrame(e)) - # try: - # if frame['payloadLength'] != len(frame['payload']): - # raise Exception + try: + if frame['payloadLength'] != len(frame['payload']): + raise Exception - # payload = self.payloads[frame['type']][frame['command']](frame['payload']) - # self.state.update(payload.getStatus()) # just overwrite ... and get the latest - # # payload.dump() + payload = self.payloads[frame['type']][frame['command']](frame['payload']) + # self.state.update(payload.getStatus()) # just overwrite ... and get the latest + payload.dump() - # except Exception as err: - # # print(err) + except Exception as err: + print(err) # print(",".join(list(map((lambda x: f'{x:02X}' if not isinstance(x, Iterable) else ' '.join(f'{b:02X}' for b in x) if len(x) > 0 else ''), list(frame.values()))))) - # pass + pass events = events[1:] diff --git a/README.md b/README.md index 46c54b2..05e2bea 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,7 @@ Some common addresses for DSTs and SRCs: | ---- | ------ | | 0F | broadcast? that is... everyone should pay attention? | | 10 | controller -- could probably MOSTLY just use message FROM this addr | -| 20 | +| 20 | wireless remote | | 60 | pump | Some common TYPEs and CMDs diff --git a/pentair-control.py b/pentair-control.py index dde05fb..71bfcf9 100755 --- a/pentair-control.py +++ b/pentair-control.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 from collections.abc import Iterable +from distutils.util import strtobool from FileReader import FileReader from Observer import * from PentairProtocol import PentairProtocol @@ -74,6 +75,16 @@ def update(self, messages): # for m in messages: # self.frames.append(self.protocol.parseFrame(m)) +class PayloadParser(Observer): + def __init__(self, payloads): + super().__init__() + self.protocol = PentairProtocol() + + self.payloads = payloads + + def update(self, frames): + self.payloads.append(list(map(self.protocol.parsePayload, frames))) + class CSVOutput(Observer): def __init__(self): super().__init__() @@ -81,8 +92,13 @@ def __init__(self): def update(self, objects): for o in objects: if len(o) > 0: - print( ",".join(list(map((lambda x: f'{x:02X}' if not isinstance(x, Iterable) else ' '.join(f'{b:02X}' for b in x) if len(x) > 0 else ''), list(o.values())))) ) - + try: + s = '' + if 'state' in o: + s = o.pop('state') + print( ",".join(list(map((lambda x: f'{x:02X}' if not isinstance(x, Iterable) else ' '.join(f'{b:02X}' for b in x) if len(x) > 0 else ''), list(o.values())))) + "," + json.dumps(s) ) + except Exception as err: + print(err) # Configure logging @@ -106,15 +122,17 @@ def update(self, objects): # 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() inFile = args.inFile timeout = float(args.timeout) +csv = strtobool(args.csv) ''' @@ -125,6 +143,7 @@ def update(self, objects): streamData = ObservableString() messages = ObservableArray() frames = ObservableArray() +# payloads = ObservableArray() if len(inFile) > 0: print(f'using {inFile} as source') @@ -146,8 +165,9 @@ def update(self, objects): frameParser = FrameParser(frames) messages.addObserver(frameParser) -output = CSVOutput() -frames.addObserver(output) +if csv: + output = CSVOutput() + frames.addObserver(output)