Exemple #1
0
def Set(devKey, newState=states.present):
    oldTime, oldState = Get(devKey)
    if oldState != newState:
        database.NewEvent(devKey, newState)  # For ActivityLog on web page
    if newState == states.absent:
        database.LogItem(
            devKey, "SignalPercentage",
            0)  # Clear down signal strength when device goes missing
    database.LogItem(devKey, "Presence", newState)
Exemple #2
0
def NoteMsgDetails(devKey, arg):
    devIndex = GetIndexFromKey(devKey)
    if devIndex == None:
        synopsis.problem("Unknown device:",str(devKey))
        return
    if arg[0] == expRsp[devIndex]:
        expRsp[devIndex] = None   # Note that we've found the expected response now, so we're now clear to send
    presence.Set(devKey) # Note presence, and update radio quality
    if isnumeric(arg[-2]):
        if int(arg[-2]) < 0: # Assume penultimate item is RSSI, and thus that ultimate one is LQI
            rssi = arg[-2]
            lqi = arg[-1]
            try:
                signal = int((int(lqi, 16) * 100) / 255)    # Convert 0-255 to 0-100.  Ignore RSSI for now
            except ValueError:
                signal = -1   # Cannot get signal
            if signal != -1:
                entry = database.GetLatestLoggedItem(devKey, "SignalPercentage")
                if entry != None:
                    oldSignal = entry[0] # Just the value
                    fmt = "%Y-%m-%d %H:%M:%S"
                    oldTimestamp = datetime.strptime(entry[1], fmt)
                    if oldSignal == None:
                        oldSignal = signal + 100  # Force an update if no previous signal
                    deltaSignal = signal - oldSignal
                    deltaTime = datetime.now() - oldTimestamp
                    if abs(deltaSignal) > 5:
                        if deltaTime.seconds > 600:  # Only note signal level that's different enough and at least 10 minutes since last one
                            database.LogItem(devKey, "SignalPercentage", signal)
                    else:   # signal is sufficiently similar to last one, so update timestamp
                        database.RefreshLoggedItem(devKey, "SignalPercentage")  # Update timestamp to avoid too many >10 minutes!
            arg.remove(rssi)
            arg.remove(lqi)
Exemple #3
0
def Get(devKey):
    entry = database.GetLatestLoggedItem(devKey, "Presence")
    if entry != None:
        #log.debug("Presence entry says " + str(entry))
        return datetime.strptime(
            entry[1], "%Y-%m-%d %H:%M:%S"), entry[0]  # Should be time, val
    else:
        database.LogItem(devKey, "Presence", states.unknown
                         )  # Set up an entry for this device for use in future
        return datetime.now(), states.unknown  # Return something for now
Exemple #4
0
def SetAttrVal(devKey, clstrId, attrId, value):
    global msp_ota
    if clstrId == zcl.Cluster.PowerConfig and attrId == zcl.Attribute.Batt_Percentage:
        SetTempVal(devKey, "GetNextBatteryAfter",
                   datetime.now() +
                   timedelta(seconds=86400))  # Ask for battery every day
        if value != "FF":
            try:
                varVal = int(
                    int(value, 16) / 2
                )  # Arrives in 0.5% increments, but drop fractional component
            except ValueError:
                varVal = None
            if varVal != None:
                log.debug("Battery is " + str(varVal) +
                          "%.  Get next reading at " +
                          str(GetTempVal(devKey, "GetNextBatteryAfter")))
                database.LogItem(devKey, "BatteryPercentage",
                                 varVal)  # For web page
                lowBatt = int(config.Get("lowBattery", "5"))
                if varVal < lowBatt:
                    devName = database.GetDeviceItem(devKey, "userName")
                    synopsis.problem(
                        devName + "_batt",
                        devName + " low battery (" + str(varVal) + "%)")
    if clstrId == zcl.Cluster.Temperature and attrId == zcl.Attribute.Celsius:
        if value != "FF9C" and value != "8000":  # Don't know where this value (of -100) comes from, but seems to mean "Illegal temp", although it should be -1'C
            try:
                varVal = int(value, 16) / 100  # Arrives in 0.01'C increments
                database.LogItem(devKey, "TemperatureCelsius",
                                 varVal)  # For web page
            except ValueError:
                log.debug("Bad temperature of " + value)
    if clstrId == zcl.Cluster.OnOff and attrId == zcl.Attribute.OnOffState:
        if isnumeric(value, 16):
            oldState = database.GetLatestLoggedValue(devKey, "State")
            if int(value, 16) == 0:
                newState = "SwitchOff"
            else:
                newState = "SwitchOn"
            if oldState != newState:
                database.UpdateLoggedItem(
                    devKey, "State",
                    newState)  # So that we can access it from the rules later
                database.NewEvent(devKey, newState)
                Rule(devKey, newState)
            expectedState = GetTempVal(devKey, "ExpectOnOff")
            if expectedState != None:
                if newState != expectedState:
                    if expectedState == "SwitchOn":
                        devcmds.SwitchOn(devKey)  # Re-issue command
                    else:  # Assume SwitchOff
                        devcmds.SwitchOff(devKey)  # Re-issue command
                else:  # We got the expected result
                    DelTempVal(devKey, "ExpectOnOff")
    if clstrId == zcl.Cluster.Time and attrId == zcl.Attribute.LocalTime:
        if isnumeric(value, 16):
            varVal = int(value,
                         16)  # Arrives in Watts, so store it in the same way
            log.debug("Raw time:" + str(varVal))
            timeStr = iottime.FromZigbee(varVal)
            log.debug("Human time:" + timeStr)
            database.UpdateLoggedItem(devKey, "Time",
                                      timeStr)  # Just store latest time string
    if clstrId == zcl.Cluster.SimpleMetering and attrId == zcl.Attribute.InstantaneousDemand:
        if isnumeric(value, 16):
            varVal = int(value,
                         16)  # Arrives in Watts, so store it in the same way
            inClstr = database.GetDeviceItem(
                devKey, "inClusters"
            )  # Assume we have a list of clusters if we get this far
            if zcl.Cluster.OnOff not in inClstr:  # Thus device is powerclamp (has simplemetering but no OnOff)
                database.UpdateLoggedItem(
                    devKey, "State",
                    str(varVal) + "W"
                )  # So that we can access it from the rules later, or show it on the web
            database.UpdateLoggedItem(devKey, "PowerReadingW",
                                      varVal)  # Just store latest reading
    if clstrId == zcl.Cluster.SimpleMetering and attrId == zcl.Attribute.CurrentSummationDelivered:
        if isnumeric(value, 16):
            varVal = int(
                value, 16
            )  # Arrives in accumulated WattHours, so store it in the same way
            database.LogItem(devKey, "EnergyConsumedWh", varVal)
    if clstrId == zcl.Cluster.IAS_Zone and attrId == zcl.Attribute.Zone_Type:
        database.SetDeviceItem(devKey, "iasZoneType", value)
    if clstrId == zcl.Cluster.Basic:
        if attrId == zcl.Attribute.Model_Name:
            database.SetDeviceItem(devKey, "modelName", value)
        if attrId == zcl.Attribute.Manuf_Name:
            database.SetDeviceItem(devKey, "manufName", value)
    if clstrId == zcl.Cluster.OTA or clstrId == msp_ota:
        if attrId == zcl.Attribute.firmwareVersion:
            database.SetDeviceItem(devKey, "firmwareVersion", value)
    if clstrId == zcl.Cluster.PollCtrl:
        if attrId == zcl.Attribute.LongPollIntervalQs:
            varVal = str(float(int(value, 16) /
                               4))  # Value arrives in units of quarter seconds
            database.SetDeviceItem(
                devKey, "longPollInterval", varVal
            )  # For web page and also to see whether to wait for CheckIn or just send messages (if <6 secs)
    if clstrId == zcl.Cluster.Thermostat:
        if attrId == zcl.Attribute.LocalTemp:
            if isnumeric(value, 16):
                varVal = int(value, 16) / 100  # Arrives in 0.01'C increments
                database.LogItem(devKey, "SourceCelsius",
                                 varVal)  # For web page
                src = varVal
                tgt = database.GetLatestLoggedValue(devKey, "TargetCelsius")
                database.UpdateLoggedItem(
                    devKey, "State", "source " + str(src) + "'C/target " +
                    str(tgt) + "'C")  # So that we can show it on the web
        if attrId == zcl.Attribute.OccupiedHeatingSetPoint:
            if isnumeric(value, 16):
                varVal = int(value, 16) / 100  # Arrives in 0.01'C increments
                database.LogItem(devKey, "TargetCelsius",
                                 varVal)  # For web page
                tgt = varVal
                src = database.GetLatestLoggedValue(devKey, "SourceCelsius")
                database.UpdateLoggedItem(
                    devKey, "State", "source " + str(src) + "'C/target " +
                    str(tgt) + "'C")  # So that we can show it on the web
    if clstrId == zcl.Cluster.Time:
        if attrId == zcl.Attribute.Time:
            if isnumeric(value, 16):
                varVal = int(value,
                             16)  # Arrives in seconds since 1st Jan 2000
                timeStamp = iottime.FromZigbee(varVal)
                database.LogItem(devKey, "time",
                                 str(timeStamp))  # For web page