Newer
Older
pyenergenie / src / monitor.py
# monitor.py  27/09/2015  D.J.Whale
#
# Monitor settings of Energine MiHome plugs

import time

from energenie import OpenHEMS, Devices
from energenie import radio
from Timer import Timer

def trace(msg):
    print(str(msg))


#----- TEST APPLICATION -------------------------------------------------------

directory = {}

def allkeys(d):
    result = ""
    for k in d:
        if len(result) != 0:
            result += ','
        result += str(k)
    return result

        
def updateDirectory(message):
    """Update the local directory with information about this device"""
    now      = time.time()
    header   = message["header"]
    sensorId = header["sensorid"]

    if not directory.has_key(sensorId):
        # new device discovered
        desc = Devices.getDescription(header["mfrid"], header["productid"])
        print("ADD device:%s %s" % (hex(sensorId), desc))
        directory[sensorId] = {"header": message["header"]}
        print(allkeys(directory))

    directory[sensorId]["time"] = now
    #TODO would be good to keep recs, but need to iterate through all and key by paramid,
    #not as a list index, else merging will be hard.


SWITCH_MESSAGE = {
    "header": {
        "mfrid":       Devices.MFRID,
        "productid":   Devices.PRODUCTID_R1_MONITOR_AND_CONTROL,
        "encryptPIP":  Devices.CRYPT_PIP,
        "sensorid":    0 # FILL IN
    },
    "recs": [
        {
            "wr":      True,
            "paramid": OpenHEMS.PARAM_SWITCH_STATE,
            "typeid":  OpenHEMS.Value.UINT,
            "length":  1,
            "value":   0 # FILL IN
        }
    ]
}


JOIN_ACK_MESSAGE = {
    "header": {
        "mfrid":       0, # FILL IN
        "productid":   0, # FILL IN
        "encryptPIP":  Devices.CRYPT_PIP,
        "sensorid":    0 # FILL IN
    },
    "recs": [
        {
            "wr":      False,
            "paramid": OpenHEMS.PARAM_JOIN,
            "typeid":  OpenHEMS.Value.UINT,
            "length":  0
        }
    ]
}



def monitor():
    """Send discovery and monitor messages, and capture any responses"""

    # Define the schedule of message polling
    sendSwitchTimer    = Timer(5, 1)   # every 5 seconds offset by initial 1
    switch_state       = 0             # OFF
    radio.receiver()
    decoded            = None

    while True:
        # See if there is a payload, and if there is, process it
        if radio.isReceiveWaiting():
            trace("receiving payload")
            payload = radio.receive()
            try:
                decoded = OpenHEMS.decode(payload)
            except OpenHEMS.OpenHEMSException as e:
                print("Can't decode payload:" + str(e))
                continue
                      
            OpenHEMS.showMessage(decoded)
            updateDirectory(decoded)
            #TODO: Should remember report time of each device,
            #and reschedule command messages to avoid their transmit slot
            #making it less likely to miss an incoming message due to
            #the radio being in transmit mode

            # assume only 1 rec in a join, for now
            if decoded["recs"][0]["paramid"] == OpenHEMS.PARAM_JOIN:
                #TODO: write OpenHEMS.getFromMessage("header_mfrid")
                response = OpenHEMS.alterMessage(JOIN_ACK_MESSAGE,
                    header_mfrid=decoded["header"]["mfrid"],
                    header_productid=decoded["header"]["productid"],
                    header_sensorid=decoded["header"]["sensorid"])
                p = OpenHEMS.encode(response)
                radio.transmitter()
                radio.transmit(p)
                radio.receiver()

        if sendSwitchTimer.check() and decoded != None:
            request = OpenHEMS.alterMessage(SWITCH_MESSAGE,
                header_sensorid=decoded["header"]["sensorid"],
                recs_0_value=switch_state)
            p = OpenHEMS.encode(request)
            radio.transmitter()
            radio.transmit(p)
            radio.receiver()
            switch_state = (switch_state+1) % 2 # toggle
        

if __name__ == "__main__":

    radio.init()
    OpenHEMS.init(Devices.CRYPT_PID)

    try:
        monitor()

    finally:
        radio.finished()

# END