Skip to content

Commit

Permalink
restore serial port and reduce non-CSV output to one state output per…
Browse files Browse the repository at this point in the history
… time cycle
  • Loading branch information
scottrfrancis committed Jul 17, 2020
1 parent af5ee70 commit 35bcf0e
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 6 deletions.
4 changes: 2 additions & 2 deletions PentairProtocol.py
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand Down Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
42 changes: 38 additions & 4 deletions pentair-control.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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__()
Expand Down Expand Up @@ -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()
Expand All @@ -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')
Expand All @@ -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)
Expand All @@ -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():
Expand Down

0 comments on commit 35bcf0e

Please sign in to comment.