def __init__(self, name, data): devices.Device.__init__(self, name, data) self.connectedTag = tagpoints.Tag("/devices/" + name + "/connected") try: self.retryConnect() except: self.handleException() self.widgets = [] self.connectedTag.setAlarm("Disconnected", "not value") for n in range(8): i = n + 1 x = widgets.Button() x.attach(self.makeWidgetHandler(i, True)) y = widgets.Button() y.attach(self.makeWidgetHandler(i, False)) t = tagpoints.Tag("/devices/" + name + "/relays[" + str(i) + "]") h = self.makeTagHandler(i) t.handlerFunction = h t.subscribe(h) self.tagPoints["ch" + str(i)] = t self.widgets.append((x, y))
def __init__(self, name, data): self.lock = threading.Lock() self.gatewayStatusTag = tagpoints.StringTag("/devices/"+name+".status") self.gatewayStatusTagClaim = self.gatewayStatusTag.claim( 'disconnected', "HWStatus", 60) self.gatewayStatusTag.setAlarm( name+".SG1GatewayDisconnected", "value != 'connected'", tripDelay=15) self.debugSwitch = widgets.Switch() self.debugSwitch.require("/admin/settings.edit") self.gatewayNoiseTag = tagpoints.Tag("/devices/"+name+".noiseFloor") self.gatewayNoiseTag.unit= "dBm" self.gatewayNoiseTag.min= -140 self.gatewayNoiseTag.max= -60 self.gatewayNoiseTag.hi= -85 self.gatewayUtilizationTag = tagpoints.Tag( "/devices/"+name+".rxUtilization") self.gatewayUtilizationTag.max =1 self.gatewayUtilizationTag.min=0 self.gatewayUtilizationTag.hi = 0.75 devices.Device.__init__(self, name, data) self.tagpoints['status'] = self.gatewayStatusTag self.tagpoints['noiseFloor'] = self.gatewayNoiseTag self.tagpoints['utilization'] = self.gatewayUtilizationTag self.gatewayNoiseTag.setAlarm( name+'.RFNoiseFloor', "value > -98", tripDelay=60) self.gatewayUtilizationTag.setAlarm( name+'.RFExcessiveChannelUtilization', "value > 0.8", tripDelay=60) self.activityThreshold = float(data.get("device.ccaThreshold", "-94")) self.gw = Gateway( kaithemInterface=weakref.ref(self), port=data.get("device.serialport", "/dev/ttyUSB0"), id=data.get("device.gatewayID", "default"), mqttServer=data.get( "device.mqttServer", "__virtual__SG1"), mqttPort=int( data.get("device.mqttPort", 1883)), rfProfile=int( data.get("device.rfProfile", 7)), channelNumber=int( data.get("device.channelNumber", 3)) ) self.gw.kaithemInterface = weakref.ref(self) self.print("GW obj created")
def doPsutil(): temps = {} t = psutil.sensors_temperatures() for i in t: peak = 0 negpeak = 100 for j in t[i]: peak = max(peak, j.current) negpeak = min(peak, j.current) #If it is very cold we can report that too, basically we want to detect whatever the main problem is #But anything under -50 is probably a placeholder value if negpeak < 0 and negpeak > -50: peak = negpeak if not i in tempTags: #Fix the name tempTags[i] = tagpoints.Tag( tagpoints.normalizeTagName("/system/sensors/temp/" + i, "_")) tempTags[i].setAlarm("temperature", "value>85") tempTags[i].unit = 'degC' tempTags[i].max = 150 tempTags[i].min = -25 tempTags[i].hi = 80 tempTags[i].lo = -5 tempTags[i].value = peak battery = psutil.sensors_battery() if battery: acPowerTag.value = battery.power_plugged batteryTag.value = battery.percent batteryTime.value = battery.secsleft if battery.secsleft > 0 else 9999999
def onHeartRate(t, m): m = float(m) if not 'heartRate' in self.tagpoints: self.tagpoints["heartRate"] = tagpoints.Tag("/devices/" + name + ".heartRate") self.tagpoints['heartRate'].value = m
def onBattery(t, m): m = float(m) if not 'battery' in self.tagpoints: self.tagpoints["battery"] = tagpoints.Tag("/devices/" + name + ".battery") self.tagpoints['battery'].value = m
def onTemp(t, m): m = float(m) if not 'temp' in self.tagpoints: self.tagpoints["temp"] = tagpoints.Tag("/devices/" + name + ".temp") self.tagpoints['temp'].unit = "degC" self.tagpoints['temp'].value = m
def onWeight(t, m): m = float(m) if not 'weight' in self.tagpoints: self.tagpoints["weight"] = tagpoints.Tag("/devices/" + name + ".weight") #self.tagpoints['weight'].unit = "pa" self.tagpoints['weight'].value = m
def onPres(t, m): m = float(m) if not 'pressure' in self.tagpoints: self.tagpoints["pressure"] = tagpoints.Tag("/devices/" + name + ".pressure") self.tagpoints['pressure'].unit = "pa" self.tagpoints['pressure'].value = m
def onHum(t, m): m = float(m) if not 'humidity' in self.tagpoints: self.tagpoints["humidity"] = tagpoints.Tag("/devices/" + name + ".humidity") self.tagpoints['humidity'].unit = "%" self.tagpoints['humidity'].min = 0 self.tagpoints['humidity'].max = 100 self.tagpoints['humidity'].value = m
try: import psutil psutil.sensors_temperatures() battery = psutil.sensors_battery() except ImportError: logging.exception("Cant load psutil, trying plyer instead") psutil = None try: import plyer except ImportError: print("Plyer not available either") if battery: batteryTag = tagpoints.Tag("/system/power/batteryLevel") batteryTag.value = battery.percent batteryTag.unit = "%" batteryTag.min = 0 batteryTag.max = 100 batteryTag.lo = 25 batteryTime = tagpoints.Tag("/system/power/batteryTime") batteryTime.unit = 's' batteryTime.max = 30 * 60 * 60 batteryTime.lo = 40 * 60 batteryTime.value = battery.secsleft if battery.secsleft > 0 else 9999999 batteryTime.setAlarm("lowBatteryTimeRemaining", "value < 60*15") acPowerTag = tagpoints.Tag("/system/power/charging") acPowerTag.value = battery.power_plugged
def __init__(self, name, data): devices.Device.__init__(self, name, data) try: self.lock = threading.Lock() self.lastSeen = 0 self.lastRSSI = -127 self.lastPathLoss = 140 self.expectedMessageInterval = float( data.get("device.expectedMessageInterval", 60)) self.localNodeID = float( data.get("device.localNodeID", 60)) self.rssiTag = tagpoints.Tag("/devices/"+name+".rssi") self.rssiTagClaim = self.rssiTag.claim(self.rssi, "HWStatus", 60) self.rssiTag.setAlarm(name+'.SG1DeviceLowSignal', "value < -94", tripDelay=(self.expectedMessageInterval*1.3)) self.rssiTag.unit = "dBm" self.rssiTag.min=-140 self.rssiTag.max = -20 self.debugSwitch = widgets.Switch() self.debugSwitch.require("/admin/settings.edit") # No redundant alarm, only alarm when auto tx power can no longer keep up self.pathLossTag = tagpoints.Tag("/devices/"+name+".pathloss") self.pathLossTagClaim = self.pathLossTag.claim( self.pathLoss, "HWStatus", 60) self.pathLossTag.unit= "dBm" self.pathLossTag.min=0 self.pathLossTag.max = 180 self.pathLossTag.hi = 90 # update at 2x the rate because nyquist or something. self.rssiTag.interval = self.expectedMessageInterval/2 self.pathLossTag.interval = self.expectedMessageInterval/2 self.tagPoints['rssi'] = self.rssiTag self.tagPoints['pathloss'] = self.pathLossTag d = str(data.get("device.channelKey", 'A'*32)) if len(d) <= 32: d += 'A'*(32-len(d)) d = d.encode("ascii") else: d = base64.b64decode(d) #legacy: nodeID, new: localNodeID self.dev = Device( kaithemInterface=weakref.ref(self), channelKey=d, remoteNodeID=int(data.get("device.remoteNodeID", int(data.get("device.nodeID", '0')))), gateways=data.get("device.gateways", "__all__").split(","), mqttServer=data.get( "device.mqttServer", "__virtual__SG1"), mqttPort=int( data.get("device.mqttPort", 1883)), localNodeID=int(data.get("device.localNodeID", '0')), ) except: self.handleError(traceback.format_exc(chain=True)) self.wakeButton = widgets.Button() self.wakeButton.attach(self.wakeButtonHandler) self.wakeButton.require("/admin/settings.edit") self.apiWidget = widgets.APIWidget() self.apiWidget.attach(self.apiWidgetHandler) self.apiWidget.require("/admin/settings.edit") self.configDataWidget = widgets.DynamicSpan() self.configDataWidget.attrs= 'style="font-family:monospace;"' self.currentConfigData = bytearray(256) self.configDataWidget.write("Unknown or loading") #We can detect missing config data by noting whether the sequence is continuous or not self.lastRecievedConfigPage = 0 self.lastSavedConfigData=0 self.writeStructured = self.dev.writeStructured self.flushStructured = self.dev.flushStructured
def testTags(): from src import tagpoints import time import gc t = tagpoints.Tag("/system/selftest") t1 = time.time() t2 = t.toMonotonic(t1) if abs(t1 - t.toWallClock(t2)) > 0.1: raise RuntimeError( "Tagpoint timescale conversion selftest failed. This may not matter. Was the sytem time changed?" ) t.value = 30 tester = [0] if not t.value == 30: raise RuntimeError("Unexpected Tag Value") def f(value, timestamp, annotation): tester[0] = value t.subscribe(f) t.value = 80 if not tester[0] == 80: raise RuntimeError("Unexpected Tag Value") c = t.claim(50, "TestClaim", 60) if not tester[0] == 50: raise RuntimeError("Tag subscription issue") del f gc.collect() c.set(8) if not tester[0] == 50: raise RuntimeError("Tag subscriber still active after being deleted") if not t.value == 8: raise RuntimeError("Unexpected Tag Value") c2 = t.claim(5, "TestClaim2", 55) if not t.value == 8: raise RuntimeError("Tag value being affected by lower priority claim") c.release() if not t.value == 5: raise RuntimeError( "Lower priority tag not taking over when higher priority released") #Now test the StringTags t = tagpoints.StringTag("/system/selftest2") t.value = "str" tester = [0] if not t.value == "str": raise RuntimeError("Unexpected Tag Value") def f(value, timestamp, annotation): tester[0] = value t.subscribe(f) t.value = "str2" if not tester[0] == "str2": raise RuntimeError("Unexpected Tag Value") c = t.claim("50", "TestClaim", 60) if not tester[0] == "50": raise RuntimeError("Tag subscription issue") del f gc.collect() c.set("8") gc.collect() if not tester[0] == "50": raise RuntimeError("Tag subscriber still active after being deleted") if not t.value == "8": raise RuntimeError("Unexpected Tag Value") c2 = t.claim("5", "TestClaim2", 55) if not t.value == "8": raise RuntimeError("Tag value being affected by lower priority claim") c.release() if not t.value == "5": raise RuntimeError( "Lower priority tag not taking over when higher priority released") x = [] def f(v, t, a): c.append(v) t1 = tagpoints.Tag("/system/selftest") t2 = tagpoints.Tag("=tv('/system/selftest') + 7") t.subscribe(f) c3 = t1.claim(1, "testClaim3", 80) if not t2.value == 1 + 7: raise RuntimeError( "Subscriber to expression tag did not trigger when dependancy updated" ) c3.set(2) if not t2.value == 2 + 7: raise RuntimeError( "Subscriber to expression tag did not trigger when dependancy updated" ) # Test tag point values derived from other values t = tagpoints.Tag("TestTagPointSelftestA") t.value = 90 t2 = tagpoints.Tag("=tv('/TestTagPointSelftestA')+10") if not t2.value == 100: raise RuntimeError("Expression tagpoint didn't work") t.value = 40 if not t2.value == 50: raise RuntimeError("Expression tagpoint didn't update, value:" + str(t2.value)) t2.setAlarm("TestTagAlarm", "value>40", priority="debug") time.sleep(0.5) if not t2.alarms['TestTagAlarm'].sm.state == 'active': raise RuntimeError("Alarm not activated, state:" + t2.alarms['TestTagAlarm'].sm.state) t.value = 0 time.sleep(3) if not t2.alarms['TestTagAlarm'].sm.state == 'cleared': raise RuntimeError("Alarm not cleared, state:" + t2.alarms['TestTagAlarm'].sm.state + " value:" + str(t2.value)) t2.alarms['TestTagAlarm'].acknowledge() if not t2.alarms['TestTagAlarm'].sm.state == 'normal': raise RuntimeError("Alarm not normal after acknowledge") t1 = tagpoints.Tag("/system/selftest/Sync1") t2 = tagpoints.Tag("/system/selftest/Sync2") t1.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t2.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t1.value = 30 time.sleep(1) if not t2.value == 30: raise RuntimeError("Tag MQTT sync feature failed") #Actually means disconnect t2.mqttConnect(server='') t1.value = 31 time.sleep(1) if t2.value == 31: raise RuntimeError("Tag MQTT sync feature failed to disconnect") #Try the other way around t2.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t1.mqttConnect(server='') t1.value = 35 time.sleep(1) if t2.value == 35: raise RuntimeError("Tag MQTT sync feature failed to disconnect") #Reconnect t1.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t1.value = 33 time.sleep(1) if not t2.value == 33: raise RuntimeError("Tag MQTT sync feature failed to reconnect") #Clear them for the next test t1.mqttConnect(server='') t2.mqttConnect(server='') gc.collect() gc.collect() t1 = tagpoints.Tag("/system/selftest/ExpireTest") t1.value = 0 c1 = t1.claim(5, priority=70) c1.setExpiration(2) if not t1.value == 5: raise RuntimeError("Unexpected tag value") time.sleep(3) if not t1.value == 0: raise RuntimeError("Claim expiration did not work") c1.set(30) if not t1.value == 30: raise RuntimeError("Claim expiration did not un-expire correctly") t1 = tagpoints.StringTag("/system/selftest/Sync1Str") t2 = tagpoints.StringTag("/system/selftest/Sync2Str") #Make sure the old tag is gone gc.collect() gc.collect() t1.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t2.mqttConnect(server="__virtual__", port=456, mqttTopic='tagsyncselftest') t1.value = "Test" time.sleep(1) if not t2.value == "Test": raise RuntimeError("Tag MQTT sync feature failed") t1.value = 90 if not t1.value == '90': raise RuntimeError("Int got into the string tag") time.sleep(1) if not t2.value == '90': raise RuntimeError("Int got into the string tag") t1 = tagpoints.Tag("/system/selftest/minmax") t1.value = 40 t1.min = 50 if not t1.value == 50: raise RuntimeError("Min was ignored") t1.value = -1000 if not t1.value == 50: raise RuntimeError("Min was ignored")
def __init__(self, name, data): devices.Device.__init__(self, name, data) try: self.tagpoints["rssi"] = tagpoints.Tag("/devices/" + name + ".rssi") self.tagpoints["rssi"].default = -180 self.tagpoints["rssi"].min = -180 self.tagpoints["rssi"].max = 12 self.tagpoints["rssi"].max = 12 self.tagpoints["rssi"].interval = float( data.get("device.interval", 5)) self.tagpoints["rssi"]._bleTimestamp = time.monotonic() data['device.id'] = data.get('device.id', '').lower().strip() self.connection = kaithemobj.kaithem.mqtt.Connection( data.get("device.server", "localhost"), int(data.get("device.port", "1883").strip() or 1883), password=data.get("device.password", "").strip(), connectionID=str("EspruinoConnection")) self.tagPoints['EspruinoHubStatus'] = self.connection.statusTag topic = data.get("device.mqtttopic", "/ble/") def onRSSI(t, m): m = float(m) self.tagpoints['rssi'].value = m def onBattery(t, m): m = float(m) if not 'battery' in self.tagpoints: self.tagpoints["battery"] = tagpoints.Tag("/devices/" + name + ".battery") self.tagpoints['battery'].value = m def onEspruino(t, m): m = json.loads(m) if not 'espruino' in self.tagpoints: self.tagpoints["espruino"] = tagpoints.tagpoints.ObjectTag( "/devices/" + name + ".espruino") self.tagpoints['espruino'].value = m def onUrl(t, m): m = json.loads(m) if not 'url' in self.tagpoints: self.tagpoints["url"] = tagpoints.tagpoints.StringTag( "/devices/" + name + ".url") self.tagpoints['url'].value = m def onTemp(t, m): m = float(m) if not 'temp' in self.tagpoints: self.tagpoints["temp"] = tagpoints.Tag("/devices/" + name + ".temp") self.tagpoints['temp'].unit = "degC" self.tagpoints['temp'].value = m def onHum(t, m): m = float(m) if not 'humidity' in self.tagpoints: self.tagpoints["humidity"] = tagpoints.Tag("/devices/" + name + ".humidity") self.tagpoints['humidity'].unit = "%" self.tagpoints['humidity'].min = 0 self.tagpoints['humidity'].max = 100 self.tagpoints['humidity'].value = m def onPres(t, m): m = float(m) if not 'pressure' in self.tagpoints: self.tagpoints["pressure"] = tagpoints.Tag("/devices/" + name + ".pressure") self.tagpoints['pressure'].unit = "pa" self.tagpoints['pressure'].value = m def onWeight(t, m): m = float(m) if not 'weight' in self.tagpoints: self.tagpoints["weight"] = tagpoints.Tag("/devices/" + name + ".weight") #self.tagpoints['weight'].unit = "pa" self.tagpoints['weight'].value = m def onHeartRate(t, m): m = float(m) if not 'heartRate' in self.tagpoints: self.tagpoints["heartRate"] = tagpoints.Tag("/devices/" + name + ".heartRate") self.tagpoints['heartRate'].value = m def onJSON(t, m): m = json.loads(m) if 'rssi' in m: onRSSI(0, m['rssi']) if 'humidity' in m: onHum(0, m['humidity']) if 'temp' in m: onTemp(0, m['temp']) if 'pressure' in m: onPres(0, m['pressure']) if 'battery' in m: onBattery(0, m['battery']) if 'espruino' in m: onEspruino(0, json.dumps(m['espruino'])) if 'weight' in m: onWeight(0, m['weight']) self.noGarbage = [ onJSON, onTemp, onHum, onPres, onEspruino, onJSON ] if data['device.id']: self.connection.subscribe(topic + "advertise/" + data['device.id'] + "/rssi", onRSSI, encoding="raw") self.connection.subscribe(topic + "advertise/" + data['device.id'] + "/temp", onTemp, encoding="raw") self.connection.subscribe(topic + "advertise/" + data['device.id'] + "/humidity", onHum, encoding="raw") self.connection.subscribe(topic + "advertise/" + data['device.id'] + "/pressure", onPres, encoding="raw") self.connection.subscribe(topic + "advertise/" + data['device.id'] + "/espruino", onEspruino, encoding="raw") self.connection.subscribe(topic + "advertise/" + data['device.id'], onJSON, encoding="raw") except: self.handleException()
def __init__(self,name,data): KasaDevice.__init__(self,name,data) #Assume no e-meter till we're told otherwise self._has_emeter = False self.analogChannels=[["W"]] self.highCurrentAlert = alerts.Alert(priority='warning', name=name+".highcurrentalert", autoAck=False) self.overCurrentAlert = alerts.Alert(priority='error', name=name+".overcurrentalert", autoAck=False) #Set it up with a tagpoint self.switchTagPoint = tagpoints.Tag("/devices/"+self.name+".switch") self.switchTagPoint.min=0 self.switchTagPoint.max=1 self.switchTagPoint.owner= "Kasa Smartplug" self.tagPoints={ "switch": self.switchTagPoint } def switchTagHandler(v,ts, a): try: self.setSwitch(0,v>=0.5) except: pass def switchTagGetter(): try: return 1 if self.getSwitch(0) else 0 except: return None self.switchTagPoint.claim(switchTagGetter) self.sth = switchTagHandler #We use the handler to set this. This means that an error will #Be raised if we try to set the tag with an unreachable device self.switchTagPoint.setHandler(switchTagHandler) #We probably don't need to poll this too often self.switchTagPoint.interval= 3600 self.tagPoints={ "switch":self.switchTagPoint } self.alerts={ "unreachableAlert":self.unreachableAlert, "lowSignalAlert": self.lowSignalAlert, 'highCurrentAlert':self.highCurrentAlert, 'overCurrentAlert':self.overCurrentAlert } self.setAlertPriorities() try: #Check RSSI as soon as we create the obj to trigger any alerts based on it. self.rssi() except: pass self.s = scheduling.scheduler.everyMinute(self._pollRssi) def onf(user,value): if 'pushed' in value: self.setSwitch(0,True) def offf(user,value): if 'pushed' in value: self.setSwitch(0,False) self.onButton = widgets.Button() self.offButton=widgets.Button() self.onButton.attach(onf) self.offButton.attach(offf) self.powerWidget = widgets.Meter(high_warn=float(data.get("alarmcurrent",1400)), max=1600,min=0)
def __init__(self,name,data): KasaDevice.__init__(self,name,data) self.lastHueChange = time.monotonic() #Set it up with a tagpoint self.switchTagPoint = tagpoints.Tag("/devices/"+self.name+".switch") self.switchTagPoint.min=0 self.switchTagPoint.max=1 self.switchTagPoint.owner= "Kasa Smartplug" self.tagPoints={ "switch": self.switchTagPoint } def switchTagHandler(v,ts, a): try: self.setSwitch(0,v>=0.5) except: pass def switchTagGetter(): try: return 1 if self.getSwitch(0) else 0 except: return None self.switchTagPoint.claim(switchTagGetter) self.sth = switchTagHandler #We use the handler to set this. This means that an error will #Be raised if we try to set the tag with an unreachable device self.switchTagPoint.setHandler(switchTagHandler) #We probably don't need to poll this too often self.switchTagPoint.interval= 3600 self.tagPoints={ "switch":self.switchTagPoint } def onf(user,value): if 'pushed' in value: self.setSwitch(0,True) def offf(user,value): if 'pushed' in value: self.setSwitch(0,False) def hsvf(user,value): if time.monotonic()-self.lastHueChange>1: self.setHSV(0,self.hwidget.value,self.swidget.value,self.vwidget.value) self.lastHueChange=time.monotonic() self.hwidget = widgets.Slider(max=360) self.swidget = widgets.Slider(max=1,step=0.01) self.vwidget = widgets.Slider(max=1,step=0.01) self.csetButton = widgets.Button() self.csetButton.attach(hsvf) self.onButton = widgets.Button() self.offButton=widgets.Button() self.onButton.attach(onf) self.offButton.attach(offf) self.huesat =-1 self.lastVal =-1 self.wasOff=True self.oldTransitionRate = -1
import time import json import os def civilTwilight(): try: if kaithemobj.kaithem.time.isDark(): return 1 else: return 0 except Exception: return -1 twilightTag = tagpoints.Tag("/sky/civilTwilight") twilightTag.min = -1 twilightTag.max = 1 twilightTag.interval = 60 twilightTag.description = "Unless overridden, 1 if dark, else 0, -1 if no location is set" twilightTag.value = civilTwilight def night(): try: if kaithemobj.kaithem.time.isNight(): return 1 else: return 0 except Exception: return -1
def setTag14(n,v,a=None): if not n in tagPoints: tagPoints[n]=tagpoints.Tag(n) tagPoints[n].min=0 tagPoints[n].max=16383 tagPoints[n].setClaimVal('default',v,timestamp=None,annotation=None)