class DigitalSensor(): def __init__(self, gpio, channel, invert=False): self.gpioname = gpio self.channel = toint(channel) if isinstance(invert, str): self.invert = str2bool(invert) else: self.invert = invert self.gpio = None self.setGPIOInstance() self.gpio.setFunction(self.channel, GPIO.IN) def __str__(self): return "DigitalSensor" def __family__(self): return "DigitalSensor" def setGPIOInstance(self): if not self.gpio: if self.gpioname != "GPIO": self.gpio = instance.deviceInstance(self.gpioname) else: self.gpio = GPIO() if self.gpio: self.gpio.setFunction(self.channel, GPIO.IN) #@request("GET", "value") @response("%d") def read(self): self.setGPIOInstance() value = self.gpio.digitalRead(self.channel) if self.invert: value = not value return int(value)
class GpioTest(unittest.TestCase): def setUp(self): self.gpio = NativeGPIO() def testGPIO(self): pins = [] for header in self.gpio.MAPPING: pins.extend([ pin['gpio'] for pin in header['map'] if 'gpio' in pin and 'alt0' not in pin and 'overlay' not in pin ]) for pin in pins: info('Testing pin {}'.format(pin)) function = self.gpio.setFunctionString(pin, 'OUT') if function == 'UNKNOWN': info('Pin {} function UNKNOWN, skipping'.format(pin)) continue self.assertEqual('OUT', function) value = self.gpio.digitalWrite(pin, 1) self.assertEqual(value, 1) value = self.gpio.digitalWrite(pin, 0) self.assertEqual(value, 0) def testPinStatus(self): pin_status = self.gpio.wildcard() info(pin_status) self.assertEqual(set(self.gpio.pins + self.gpio.overlay_pins), set(pin_status.keys())) for key, value in pin_status.items(): self.assertCountEqual(value.keys(), ('function', 'value')) if key in self.gpio.pins: self.assertGreaterEqual(value['value'], 0) self.assertLessEqual(value['value'], 1)
def __init__(self): self.sensorMutex = RLock() self.systemMutex = RLock() self.continueMonitoring = False self.onDataChanged = None self.onSystemInfo = None self.currentBusInfo = self.previousBusInfo = None self.currentSensorsInfo = self.previousSensorsInfo = None self.currentSystemInfo = self.previousSystemInfo = None self.cpuLoadValues = {} self.disabledSensors = {} self.sensorsRefreshCount = 0 self.retrievingSystemInfo = False self.disabledSensorTable = "disabled_sensors" self.systemInfoRefreshList = [] checkAllBus() self.gpio = GPIO() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.StartMonitoring()
def getMessageBody(self, inviteCode): body = {'id': inviteCode} hardware = Hardware() if hardware.Serial and hardware.isRaspberryPi(): body['type'] = 'rpi' body['hardware_id'] = hardware.Serial else: hardware_id = hardware.getMac() if hardware_id: body['type'] = 'mac' body['hardware_id'] = hardware_id try: system_data = [] cayennemqtt.DataChannel.add(system_data, cayennemqtt.SYS_HARDWARE_MAKE, value=hardware.getManufacturer(), type='string', unit='utf8') cayennemqtt.DataChannel.add(system_data, cayennemqtt.SYS_HARDWARE_MODEL, value=hardware.getModel(), type='string', unit='utf8') system_info = SystemInfo() capacity_data = system_info.getMemoryInfo((cayennemqtt.CAPACITY, )) capacity_data += system_info.getDiskInfo((cayennemqtt.CAPACITY, )) for item in capacity_data: system_data.append(item) body['properties'] = {} body['properties']['pinmap'] = NativeGPIO().MAPPING if system_data: body['properties']['sysinfo'] = system_data except: exception('Error getting system info') return json.dumps(body)
def __init__(self): """Initialize the bus and sensor info and start monitoring sensor states""" self.sensorMutex = RLock() self.realTimeMutex = RLock() self.exiting = Event() self.onDataChanged = None self.systemData = [] self.currentSystemState = [] self.currentRealTimeData = {} self.queuedRealTimeData = {} self.disabledSensors = {} self.disabledSensorTable = "disabled_sensors" checkAllBus() self.gpio = GPIO() self.downloadSpeed = DownloadSpeed(Config(APP_SETTINGS)) self.downloadSpeed.getDownloadSpeed() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.realTimeMonitorRunning = False self.pluginManager = PluginManager(self.OnPluginChange) self.pluginManager.load_plugins() self.InitCallbacks() self.StartMonitoring()
def setGPIOInstance(self): if not self.gpio: if self.gpioname != "GPIO": self.gpio = instance.deviceInstance(self.gpioname) else: self.gpio = GPIO() if self.gpio: self.gpio.setFunction(self.channel, GPIO.IN)
def __init__(self, client): """Initialize the bus and sensor info and start monitoring sensor states""" self.cloudClient = client self.sensorMutex = RLock() self.realTimeMutex = RLock() self.exiting = Event() self.onDataChanged = None self.systemData = [] self.currentSystemState = [] self.currentRealTimeData = {} self.queuedRealTimeData = {} self.disabledSensors = {} self.disabledSensorTable = "disabled_sensors" checkAllBus() self.gpio = GPIO() # self.downloadSpeed = DownloadSpeed(Config(APP_SETTINGS)) # self.downloadSpeed.getDownloadSpeed() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") if not DYNAMIC_DEVICES: warn("loadJsonDevices is None") for sensor in sensors.values(): # info('--------{} {} {}'.format(sensor['name'], sensor['description'], sensor['device'])) self.AddSensor(sensor['name'], sensor['description'], sensor['device'], sensor['args']) # # info(DYNAMIC_DEVICES) self.config = Config(APP_SETTINGS) self.clientId = self.config.get('Agent', 'ClientID', None) self.mqtt_dis_prefix = self.config.get('Agent', 'MQTT_DIS_PREFIX', "homeassistant") self.serial = self.cloudClient.hardware.Serial for name, device in DYNAMIC_DEVICES.items(): for type in device['type']: if type in ['DAC', 'ADC']: continue topic, message = self.AddMQTTSensorDevice(name, type, device) if self.cloudClient: info("{} {}".format(topic, message)) self.cloudClient.EnqueuePacket(message, topic) # info(mqttsensor) results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.realTimeMonitorRunning = False self.pluginManager = PluginManager(self.OnPluginChange) self.pluginManager.load_plugins() self.InitCallbacks() self.StartMonitoring()
class GpioTest(unittest.TestCase): def setUp(self): self.gpio = NativeGPIO() def testGPIO(self): pins = [] for header in self.gpio.MAPPING: pins.extend([ pin['gpio'] for pin in header['map'] if 'gpio' in pin and 'alt0' not in pin and 'overlay' not in pin ]) for pin in pins: info('Testing pin {}'.format(pin)) function = self.gpio.setFunctionString(pin, 'OUT') if function == 'UNKNOWN': info('Pin {} function UNKNOWN, skipping'.format(pin)) continue self.assertEqual('OUT', function) value = self.gpio.digitalWrite(pin, 1) self.assertEqual(value, 1) value = self.gpio.digitalWrite(pin, 0) self.assertEqual(value, 0) def testPinStatus(self): pin_status = self.gpio.wildcard() info(pin_status) self.assertEqual(set(self.gpio.pins + self.gpio.overlay_pins), set(pin_status.keys())) for key, value in pin_status.items(): self.assertCountEqual(value.keys(), ('function', 'value')) if key in self.gpio.pins: self.assertGreaterEqual(value['value'], 0) self.assertLessEqual(value['value'], 1) def edgeCallback(self, data, value): info('edgeCallback data {}, value {}'.format(data, value)) self.callback_data = data def testEdgeCallback(self): self.callback_data = 0 pin = 27 self.gpio.setFunctionString(pin, 'IN') self.gpio.setCallback(pin, self.edgeCallback, pin) for x in range(15): if self.callback_data != 0: break time.sleep(1) self.assertEqual(pin, self.callback_data)
def __init__(self): """Initialize the bus and sensor info and start monitoring sensor states""" self.sensorMutex = RLock() self.exiting = Event() self.onDataChanged = None self.onSystemInfo = None self.systemData = [] self.currentSystemState = [] self.disabledSensors = {} self.disabledSensorTable = "disabled_sensors" checkAllBus() self.gpio = GPIO() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.StartMonitoring()
class SensorsClient(): def __init__(self): self.sensorMutex = RLock() self.systemMutex = RLock() self.continueMonitoring = False self.onDataChanged = None self.onSystemInfo = None self.currentBusInfo = self.previousBusInfo = None self.currentSensorsInfo = self.previousSensorsInfo = None self.currentSystemInfo = self.previousSystemInfo = None self.cpuLoadValues = {} self.disabledSensors = {} self.sensorsRefreshCount = 0 self.retrievingSystemInfo = False self.disabledSensorTable = "disabled_sensors" self.systemInfoRefreshList = [] checkAllBus() self.gpio = GPIO() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.StartMonitoring() def SetDataChanged(self, onDataChanged=None, onSystemInfo=None): #one parameter only that contains data in a dictionary for changed items only self.onDataChanged = onDataChanged self.onSystemInfo = onSystemInfo def StartMonitoring(self): self.continueMonitoring = True #thread = Thread(target = self.Monitor) #thread.start() ThreadPool.Submit(self.Monitor) def StopMonitoring(self): self.continueMonitoring = False def Monitor(self): nextTime = datetime.now() nextTimeSystemInfo = datetime.now() debug('Monitoring sensors and os resources started') while self.continueMonitoring: try: if datetime.now() > nextTime: self.raspberryValue = None self.raspberryValue = {} refreshTime = int(time()) if datetime.now() > nextTimeSystemInfo: with self.systemMutex: if not self.retrievingSystemInfo: ThreadPool.Submit( self.MonitorSystemInformation()) nextTimeSystemInfo = datetime.now() + timedelta( seconds=5) self.MonitorSensors() self.MonitorBus() if self.onDataChanged != None: self.onDataChanged(self.raspberryValue) bResult = self.RemoveRefresh(refreshTime) if bResult == True and self.onSystemInfo != None: self.onSystemInfo() self.sensorsRefreshCount += 1 nextTime = datetime.now() + timedelta( seconds=REFRESH_FREQUENCY) sleep(REFRESH_FREQUENCY) except: exception("Monitoring sensors and os resources failed: " + str()) debug('Monitoring sensors and os resources Finished') def MonitorSensors(self): if self.continueMonitoring == False: return debug( str(time()) + ' Get sensors info ' + str(self.sensorsRefreshCount)) self.SensorsInfo() debug( str(time()) + ' Got sensors info ' + str(self.sensorsRefreshCount)) with self.sensorMutex: if self.SHA_Calc(self.currentSensorsInfo) != self.SHA_Calc( self.previousSensorsInfo): #do merge mergedSensors = self.ChangedSensorsList() if self.previousSensorsInfo: del self.previousSensorsInfo self.previousSensorsInfo = None if mergedSensors == None: self.previousSensorsInfo = self.currentSensorsInfo return self.raspberryValue['SensorsInfo'] = mergedSensors self.previousSensorsInfo = self.currentSensorsInfo debug( str(time()) + ' Merge sensors info ' + str(self.sensorsRefreshCount)) def ChangedSensorsList(self): if self.continueMonitoring == False: return None if self.previousSensorsInfo == None: return None if self.currentSensorsInfo == None: return None changedSensors = [] previousSensorsDictionary = dict( (i['sensor'], i) for i in self.previousSensorsInfo) for item in self.currentSensorsInfo: oldItem = None if item['sensor'] in previousSensorsDictionary: oldItem = previousSensorsDictionary[item['sensor']] if self.SHA_Calc(item) != self.SHA_Calc(oldItem): changedSensors.append(item) else: changedSensors.append(item) return changedSensors def MonitorBus(self): if self.continueMonitoring == False: return debug(str(time()) + ' Get bus info ' + str(self.sensorsRefreshCount)) self.BusInfo() debug(str(time()) + ' Got bus info ' + str(self.sensorsRefreshCount)) if self.SHA_Calc(self.currentBusInfo) != self.SHA_Calc( self.previousBusInfo): self.raspberryValue['BusInfo'] = self.currentBusInfo if self.previousBusInfo: del self.previousBusInfo self.previousBusInfo = None self.previousBusInfo = self.currentBusInfo def MonitorSystemInformation(self): if self.continueMonitoring == False: return debug( str(time()) + ' Get system info ' + str(self.sensorsRefreshCount)) self.SystemInformation() debug( str(time()) + ' Got system info ' + str(self.sensorsRefreshCount)) firstSHA = self.SHA_Calc(self.currentSystemInfo) secondSHA = self.SHA_Calc(self.previousSystemInfo) if firstSHA != secondSHA: if self.previousSystemInfo: del self.previousSystemInfo self.previousSystemInfo = None self.previousSystemInfo = self.currentSystemInfo self.raspberryValue['SystemInfo'] = self.currentSystemInfo def SystemInformation(self): with self.systemMutex: self.retrievingSystemInfo = True try: jsonInfo = "{}" debug('SystemInfo Spawning child process from pid:' + str(getpid())) (jsonInfo, retCode) = services.ServiceManager.ExecuteCommand( "python3 -m myDevices.os.getsysteminfo") if int(retCode) == 0: newSystemInfo = loads(jsonInfo) if self.currentSystemInfo: del self.currentSystemInfo self.currentSystemInfo = None self.currentSystemInfo = newSystemInfo del jsonInfo from myDevices.os.cpu import GetCpuLoad cpuLoad = GetCpuLoad() newCpuLoadValues = cpuLoad.getcpuload() if newCpuLoadValues['cpu'] != 0.0: self.cpuLoadValues = newCpuLoadValues self.currentSystemInfo['CpuLoad'] = self.cpuLoadValues except Exception as ex: exception('SystemInformation failed: ' + str(ex)) with self.systemMutex: self.retrievingSystemInfo = False return self.currentSystemInfo def SHA_Calc(self, object): if object == None: return '' try: strVal = dumps(object) except: exception('SHA_Calc failed for:' + str(object)) return '' return self.SHA_Calc_str(strVal) def SHA_Calc_str(self, stringVal): m = sha1() m.update(stringVal.encode('utf8')) sDigest = str(m.hexdigest()) return sDigest def AppendToDeviceList(self, device_list, source, device_type): device = source.copy() del device['origin'] device['name'] = parse.unquote(device['name']) device['type'] = device_type if len(source['type']) > 1: device['hash'] = self.SHA_Calc_str(device['name'] + device['type']) else: device['hash'] = self.SHA_Calc_str(device['name'] + device['device']) if device['hash'] in self.disabledSensors: device['enabled'] = 0 else: device['enabled'] = 1 device_list.append(device) def GetDevices(self): device_list = manager.getDeviceList() devices = [] for dev in device_list: try: if len(dev['type']) == 0: self.AppendToDeviceList(devices, dev, '') else: for device_type in dev['type']: self.AppendToDeviceList(devices, dev, device_type) except: exception("Failed to get device: {}".format(dev)) return devices def CallDeviceFunction(self, func, *args): result = func(*args) if result != None: if hasattr(func, "contentType"): if func.contentType != M_JSON: value_type = type(result) response = value_type(func.format % result) else: response = result else: response = result return response def BusInfo(self): json = {} for (bus, value) in BUSLIST.items(): json[bus] = int(value["enabled"]) gpios = {} for gpio in range(GPIO.GPIO_COUNT): gpios[gpio] = {} gpios[gpio]['function'] = self.gpio.getFunctionString(gpio) gpios[gpio]['value'] = int(self.gpio.input(gpio)) json['GPIO'] = gpios json['GpioMap'] = MAPPING self.currentBusInfo = json return self.currentBusInfo def SensorsInfo(self): with self.sensorMutex: devices = self.GetDevices() debug( str(time()) + ' Got devices info ' + str(self.sensorsRefreshCount)) if devices is None: return {} for value in devices: sensor = instance.deviceInstance(value['name']) if 'enabled' not in value or value['enabled'] == 1: sleep(SENSOR_INFO_SLEEP) try: if value['type'] == 'Temperature': value['Celsius'] = self.CallDeviceFunction( sensor.getCelsius) value['Fahrenheit'] = self.CallDeviceFunction( sensor.getFahrenheit) value['Kelvin'] = self.CallDeviceFunction( sensor.getKelvin) if value['type'] == 'Pressure': value['Pascal'] = self.CallDeviceFunction( sensor.getPascal) if value['type'] == 'Luminosity': value['Lux'] = self.CallDeviceFunction( sensor.getLux) if value['type'] == 'Distance': value['Centimeter'] = self.CallDeviceFunction( sensor.getCentimeter) value['Inch'] = self.CallDeviceFunction( sensor.getInch) if value['type'] in ('ADC', 'DAC', 'PWM'): value['channelCount'] = self.CallDeviceFunction( sensor.analogCount) value['maxInteger'] = self.CallDeviceFunction( sensor.analogMaximum) value['resolution'] = self.CallDeviceFunction( sensor.analogResolution) value['allInteger'] = self.CallDeviceFunction( sensor.analogReadAll) value['allVolt'] = self.CallDeviceFunction( sensor.analogReadAllVolt) value['allFloat'] = self.CallDeviceFunction( sensor.analogReadAllFloat) if value['type'] in ('DAC'): value['vref'] = self.CallDeviceFunction( sensor.analogReference) if value['type'] == 'PWM': value['channelCount'] = self.CallDeviceFunction( sensor.pwmCount) value['maxInteger'] = self.CallDeviceFunction( sensor.pwmMaximum) value['resolution'] = self.CallDeviceFunction( sensor.pwmResolution) value['all'] = self.CallDeviceFunction( sensor.pwmWildcard) if value['type'] == 'Humidity': value['float'] = self.CallDeviceFunction( sensor.getHumidity) value['percent'] = self.CallDeviceFunction( sensor.getHumidityPercent) if value['type'] == 'PiFaceDigital': value['all'] = self.CallDeviceFunction( sensor.readAll) if value['type'] in ('DigitalSensor', 'DigitalActuator'): value['value'] = self.CallDeviceFunction( sensor.read) if value['type'] == 'GPIOPort': value['channelCount'] = self.CallDeviceFunction( sensor.digitalCount) value['all'] = self.CallDeviceFunction( sensor.wildcard) if value['type'] == 'AnalogSensor': value['integer'] = self.CallDeviceFunction( sensor.read) value['float'] = self.CallDeviceFunction( sensor.readFloat) value['volt'] = self.CallDeviceFunction( sensor.readVolt) if value['type'] == 'ServoMotor': value['angle'] = self.CallDeviceFunction( sensor.readAngle) if value['type'] == 'AnalogActuator': value['float'] = self.CallDeviceFunction( sensor.readFloat) except: exception("Sensor values failed: " + value['type'] + " " + value['name']) try: if 'hash' in value: value['sensor'] = value['hash'] del value['hash'] except KeyError: pass if self.currentSensorsInfo: del self.currentSensorsInfo self.currentSensorsInfo = None self.currentSensorsInfo = devices devices = None if self.sensorsRefreshCount == 0: info('System sensors info at start ' + str(self.currentSensorsInfo)) debug(('New sensors info retrieved: {}').format( self.sensorsRefreshCount)) logJson('Sensors Info updated: ' + str(self.currentSensorsInfo)) return self.currentSensorsInfo def AddSensor(self, name, description, device, args): info('AddSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorAdd = {} if name: sensorAdd['name'] = req.pathname2url(name) if device: sensorAdd['device'] = device if args: sensorAdd['args'] = args if description: sensorAdd['description'] = description with self.sensorMutex: retValue = manager.addDeviceJSON(sensorAdd) info('Add device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True self.AddRefresh() except: bVal = False return bVal def EditSensor(self, name, description, device, args): info('EditSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorEdit = {} name = req.pathname2url(name) sensorEdit['name'] = name sensorEdit['device'] = device sensorEdit['description'] = description sensorEdit['args'] = args with self.sensorMutex: retValue = manager.updateDevice(name, sensorEdit) info('Edit device returned: {}'.format(retValue)) try: hashKey = self.SHA_Calc_str(name + device) with self.sensorMutex: if self.currentSensorsInfo: currentSensorsDictionary = dict( (i['sensor'], i) for i in self.currentSensorsInfo) sensorData = currentSensorsDictionary[hashKey] sensor = sensorData[hashKey] raspberryValue = {} sensor['args'] = args sensor['description'] = description raspberryValue['SensorsInfo'] = [] raspberryValue['SensorsInfo'].append(sensor) if self.onDataChanged != None: self.onDataChanged(raspberryValue) except: pass if retValue[0] == 200: bVal = True self.AddRefresh() except: exception("Edit sensor failed") bVal = False return bVal def DeleteSensor(self, name): bVal = False try: sensorRemove = req.pathname2url(name) with self.sensorMutex: retValue = manager.removeDevice(sensorRemove) info('Remove device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True self.AddRefresh() except: exception("Remove sensor failed") bVal = False return bVal def RemoveSensor(self, name): debug('') return self.DeleteSensor(name) def EnableSensor(self, sensor, enable): #sensor is the hash composed from name and device class/type info('Enable sensor: ' + str(sensor) + ' ' + str(enable)) try: if sensor is None: return False if enable is None: return False with self.sensorMutex: if enable == 0: #add item to the list if sensor not in self.disabledSensors: rowId = DbManager.Insert(self.disabledSensorTable, sensor) self.disabledSensors[sensor] = 1 else: #remove item from the list if sensor in self.disabledSensors: DbManager.Delete(self.disabledSensorTable, sensor) del self.disabledSensors[sensor] #save list except Exception as ex: error('EnableSensor Failed with exception: ' + str(ex)) return False self.AddRefresh() return True def AddRefresh(self): self.systemInfoRefreshList.append(int(time())) def RemoveRefresh(self, newRefresh): bReturn = False for i in self.systemInfoRefreshList: if i < newRefresh: self.systemInfoRefreshList.remove(i) bReturn = True return bReturn def GpioCommand(self, commandType, method, channel, value): debug('') info('GpioCommand ' + commandType + ' method ' + method + ' Channel: ' + str(channel) + ' Value: ' + str(value)) if commandType == 'function': if method == 'POST': debug('setFunction:' + str(channel) + ' ' + str(value)) return str(self.gpio.setFunctionString(channel, value)) if method == 'GET': debug('getFunction:' + str(channel) + ' ' + str(value)) return str(self.gpio.getFunctionString(channel)) if commandType == 'value': if method == 'POST': debug('digitalWrite:' + str(channel) + ' ' + str(value)) retVal = str(self.gpio.digitalWrite(channel, value)) return retVal if method == 'GET': debug('digitalRead:' + str(channel)) return str(self.gpio.digitalRead(channel)) if commandType == 'integer': if method == 'POST': debug('portWrite:' + str(value)) return str(self.gpio.portWrite(value)) if method == 'GET': debug('portRead:') return str(self.gpio.portRead()) debug.log('GpioCommand not set') return 'failure' def SensorCommand(self, commandType, sensorName, sensorType, driverClass, method, channel, value): retVal = False info( 'SensorCommand: {} SensorName {} SensorType {} DriverClass {} Method {} Channel {} Value {}' .format(commandType, sensorName, sensorType, driverClass, method, channel, value)) try: self.AddRefresh() debug('') actuators = ('GPIOPort', 'ServoMotor', 'AnalogActuator', 'LoadSensor', 'PiFaceDigital', 'DistanceSensor', 'Thermistor', 'Photoresistor', 'LightDimmer', 'LightSwitch', 'DigitalSensor', 'DigitalActuator', 'MotorSwitch', 'RelaySwitch', 'ValveSwitch', 'MotionSensor') gpioExtensions = ('GPIOPort', 'PiFaceDigital') if driverClass is None: hashKey = self.SHA_Calc_str(sensorName + sensorType) else: hashKey = self.SHA_Calc_str(sensorName + driverClass) with self.sensorMutex: if hashKey in self.disabledSensors: return retVal sensor = instance.deviceInstance(sensorName) if not sensor: info('Sensor not found') return retVal if (sensorType in actuators) or (driverClass in actuators): if sensorType in gpioExtensions or driverClass in gpioExtensions: if commandType == 'integer' or commandType == 'value': retVal = str( self.CallDeviceFunction( sensor.write, int(channel), int(value))) return retVal else: if commandType == 'integer': retVal = str( self.CallDeviceFunction( sensor.write, int(value))) return retVal if commandType == 'function': retVal = str( self.CallDeviceFunction(sensor.setFunctionString, channel, value)) return retVal if commandType == 'angle': retVal = self.CallDeviceFunction( sensor.writeAngle, value) return retVal if commandType == 'float': retVal = self.CallDeviceFunction( sensor.writeFloat, float(value)) return retVal if commandType == 'integer': retVal = float( self.CallDeviceFunction(sensor.write, int(channel), int(value))) return retVal if commandType == 'float': retVal = float( self.CallDeviceFunction(sensor.writeFloat, int(channel), float(value))) return retVal if commandType == 'volt': retVal = float( self.CallDeviceFunction(sensor.writeVolt, int(channel), float(value))) return retVal if commandType == 'angle': retVal = float( self.CallDeviceFunction(sensor.writeAngle, int(channel), float(value))) return retVal warn('Command not implemented: ' + commandType) return retVal except Exception as ex: exception('SensorCommand failed with: ' + str(ex)) pass finally: #looks like this breaks actuators refresh by updating and not sending data changed #then refresh never comes for the specific sensor #ThreadPool.SubmitParam(self.Monitor, hashKey) return retVal
def setUp(self): self.gpio = NativeGPIO()
class SensorsClient(): """Class for interfacing with sensors and actuators""" def __init__(self): """Initialize the bus and sensor info and start monitoring sensor states""" self.sensorMutex = RLock() self.realTimeMutex = RLock() self.exiting = Event() self.onDataChanged = None self.systemData = [] self.currentSystemState = [] self.currentRealTimeData = {} self.queuedRealTimeData = {} self.disabledSensors = {} self.disabledSensorTable = "disabled_sensors" checkAllBus() self.gpio = GPIO() self.downloadSpeed = DownloadSpeed(Config(APP_SETTINGS)) self.downloadSpeed.getDownloadSpeed() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.realTimeMonitorRunning = False self.pluginManager = PluginManager(self.OnPluginChange) self.pluginManager.load_plugins() self.InitCallbacks() self.StartMonitoring() def SetDataChanged(self, onDataChanged=None): """Set callback to call when data has changed Args: onDataChanged: Function to call when sensor data changes """ self.onDataChanged = onDataChanged def QueueRealTimeData(self, name, data): """Add real-time data to queue to be sent on thread Args: name: The name to use for the data data: The data to send """ with self.realTimeMutex: if name not in self.currentRealTimeData: self.currentRealTimeData[name] = data else: self.queuedRealTimeData[name] = data def OnSensorChange(self, device, value): """Callback that is called when digital sensor data has changed Args: device: The device that has changed data value: The new data value """ debug('OnSensorChange: {}, {}'.format(device, value)) with self.realTimeMutex: data = {'name': device['description'], 'value': value, 'type': 'digital_sensor', 'unit': 'd'} if 'args' in device: data['args'] = device['args'] self.QueueRealTimeData(device['name'], data) def OnPluginChange(self, data): """Callback that is called when digital sensor data has changed Args: data: The new data value """ debug('OnPluginChange: {}'.format(data)) self.QueueRealTimeData(data['id'], data) with self.realTimeMutex: if not self.realTimeMonitorRunning: ThreadPool.Submit(self.RealTimeMonitor) def OnGpioStateChange(self, channel, value): """Send updated pin state when it has changed Args: channel: The pin number value: The new value for the pin """ debug('OnGpioStateChange: channel {}, value {}'.format(channel, value)) data = [] cayennemqtt.DataChannel.add_unique(data, cayennemqtt.SYS_GPIO, channel, cayennemqtt.VALUE, value) if not self.realTimeMonitorRunning: self.onDataChanged(data) else: self.QueueRealTimeData(data[0]['channel'], data[0]) def InitCallbacks(self): """Set callback function for any digital devices that support them""" devices = manager.getDeviceList() for device in devices: sensor = instance.deviceInstance(device['name']) if 'DigitalSensor' in device['type'] and hasattr(sensor, 'setCallback'): debug('Set callback for {}'.format(sensor)) sensor.setCallback(self.OnSensorChange, device) if not self.realTimeMonitorRunning: ThreadPool.Submit(self.RealTimeMonitor) def RemoveCallbacks(self): """Remove callback function for all digital devices""" devices = manager.getDeviceList() for device in devices: sensor = instance.deviceInstance(device['name']) if 'DigitalSensor' in device['type'] and hasattr(sensor, 'removeCallback'): sensor.removeCallback() def StartMonitoring(self): """Start thread monitoring sensor data""" ThreadPool.Submit(self.Monitor) def StopMonitoring(self): """Stop thread monitoring sensor data""" self.RemoveCallbacks() self.exiting.set() def Monitor(self): """Monitor bus/sensor states and system info and report changed data via callbacks""" debug('Monitoring sensors and os resources started') sendAllDataCount = 0 nextTime = datetime.now() while not self.exiting.is_set(): try: difference = nextTime - datetime.now() delay = min(REFRESH_FREQUENCY, difference.total_seconds()) delay = max(0, delay) if not self.exiting.wait(delay): nextTime = datetime.now() + timedelta(seconds=REFRESH_FREQUENCY) self.currentSystemState = [] self.MonitorSystemInformation() self.MonitorSensors() self.MonitorPlugins() self.MonitorBus() if self.currentSystemState != self.systemData: data = self.currentSystemState if self.systemData and not sendAllDataCount == 0: data = [x for x in self.currentSystemState if x not in self.systemData] if self.onDataChanged and data: self.onDataChanged(data) sendAllDataCount += 1 if sendAllDataCount >= 4: sendAllDataCount = 0 self.systemData = self.currentSystemState except: exception('Monitoring sensors and os resources failed') debug('Monitoring sensors and os resources finished') def RealTimeMonitor(self): """Monitor real-time state changes and report changed data via callbacks""" self.realTimeMonitorRunning = True info('Monitoring real-time state changes') nextTime = datetime.now() while not self.exiting.is_set(): try: if not self.exiting.wait(0.5): if datetime.now() > nextTime: nextTime = datetime.now() + timedelta(seconds=REAL_TIME_FREQUENCY) self.SendRealTimeData() except: exception('Monitoring real-time changes failed') debug('Monitoring real-time changes finished') self.realTimeMonitorRunning = False def SendRealTimeData(self): """Send real-time data via callback""" data = [] with self.realTimeMutex: if self.currentRealTimeData: for name, item in self.currentRealTimeData.items(): if cayennemqtt.SYS_GPIO in name: data.append(item) else: cayennemqtt.DataChannel.add_unique(data, cayennemqtt.DEV_SENSOR, name, value=item['value'], name=item['name'], type=item['type'], unit=item['unit']) try: cayennemqtt.DataChannel.add_unique(data, cayennemqtt.SYS_GPIO, item['args']['channel'], cayennemqtt.VALUE, item['value']) except: pass if name in self.queuedRealTimeData and self.queuedRealTimeData[name]['value'] == item['value']: del self.queuedRealTimeData[name] self.currentRealTimeData = self.queuedRealTimeData self.queuedRealTimeData = {} if data: self.onDataChanged(data) def MonitorSensors(self): """Check sensor states for changes""" if self.exiting.is_set(): return self.currentSystemState += self.SensorsInfo() def MonitorPlugins(self): """Check plugin states for changes""" if self.exiting.is_set(): return self.currentSystemState += self.pluginManager.get_plugin_readings() def MonitorBus(self): """Check bus states for changes""" if self.exiting.is_set(): return self.currentSystemState += self.BusInfo() def MonitorSystemInformation(self): """Check system info for changes""" if self.exiting.is_set(): return self.currentSystemState += self.SystemInformation() def SystemInformation(self): """Return dict containing current system info, including CPU, RAM, storage and network info""" newSystemInfo = [] try: systemInfo = SystemInfo() newSystemInfo = systemInfo.getSystemInformation() download_speed = self.downloadSpeed.getDownloadSpeed() if download_speed: cayennemqtt.DataChannel.add(newSystemInfo, cayennemqtt.SYS_NET, suffix=cayennemqtt.SPEEDTEST, value=download_speed, type='bw', unit='mbps') except Exception: exception('SystemInformation failed') return newSystemInfo def CallDeviceFunction(self, func, *args): """Call a function for a sensor/actuator device and format the result value type Args: func: Function to call args: Parameters to pass to the function Returns: True for success, False otherwise. """ result = func(*args) if result != None: if hasattr(func, "contentType"): if func.contentType != M_JSON: value_type = type(result) response = value_type(func.format % result) else: response = result else: response = result return response def BusInfo(self): """Return a dict with current bus info""" bus_info = [] gpio_state = self.gpio.wildcard() for key, value in gpio_state.items(): cayennemqtt.DataChannel.add(bus_info, cayennemqtt.SYS_GPIO, key, cayennemqtt.VALUE, value['value']) cayennemqtt.DataChannel.add(bus_info, cayennemqtt.SYS_GPIO, key, cayennemqtt.FUNCTION, value['function']) return bus_info def SensorsInfo(self): """Return a list with current sensor states for all enabled sensors""" manager.deviceDetector() devices = manager.getDeviceList() sensors_info = [] if devices is None: return sensors_info for device in devices: sensor = instance.deviceInstance(device['name']) if 'enabled' not in device or device['enabled'] == 1: sensor_types = {'Temperature': {'function': 'getCelsius', 'data_args': {'type': 'temp', 'unit': 'c'}}, 'Humidity': {'function': 'getHumidityPercent', 'data_args': {'type': 'rel_hum', 'unit': 'p'}}, 'Pressure': {'function': 'getPascal', 'data_args': {'type': 'bp', 'unit': 'pa'}}, 'Luminosity': {'function': 'getLux', 'data_args': {'type': 'lum', 'unit': 'lux'}}, 'Distance': {'function': 'getCentimeter', 'data_args': {'type': 'prox', 'unit': 'cm'}}, 'ServoMotor': {'function': 'readAngle', 'data_args': {'type': 'analog_actuator'}}, 'DigitalSensor': {'function': 'read', 'data_args': {'type': 'digital_sensor', 'unit': 'd'}}, 'DigitalActuator': {'function': 'read', 'data_args': {'type': 'digital_actuator', 'unit': 'd'}}, 'AnalogSensor': {'function': 'readFloat', 'data_args': {'type': 'analog_sensor'}}, 'AnalogActuator': {'function': 'readFloat', 'data_args': {'type': 'analog_actuator'}}} # extension_types = {'ADC': {'function': 'analogReadAllFloat'}, # 'DAC': {'function': 'analogReadAllFloat'}, # 'PWM': {'function': 'pwmWildcard'}, # 'GPIOPort': {'function': 'wildcard'}} for device_type in device['type']: try: display_name = device['description'] except: display_name = None if device_type in sensor_types: try: sensor_type = sensor_types[device_type] func = getattr(sensor, sensor_type['function']) if len(device['type']) > 1: channel = '{}:{}'.format(device['name'], device_type.lower()) else: channel = device['name'] value = self.CallDeviceFunction(func) cayennemqtt.DataChannel.add(sensors_info, cayennemqtt.DEV_SENSOR, channel, value=value, name=display_name, **sensor_type['data_args']) if 'DigitalActuator' == device_type and value in (0, 1): manager.updateDeviceState(device['name'], value) except: exception('Failed to get sensor data: {} {}'.format(device_type, device['name'])) # else: # try: # extension_type = extension_types[device_type] # func = getattr(sensor, extension_type['function']) # values = self.CallDeviceFunction(func) # for pin, value in values.items(): # cayennemqtt.DataChannel.add(sensors_info, cayennemqtt.DEV_SENSOR, device['name'] + ':' + str(pin), cayennemqtt.VALUE, value, name=display_name) # except: # exception('Failed to get extension data: {} {}'.format(device_type, device['name'])) info('Sensors info: {}'.format(sensors_info)) return sensors_info def AddSensor(self, name, description, device, args): """Add a new sensor/actuator Args: name: Name of sensor to add description: Sensor description device: Sensor device class args: Sensor specific args Returns: True for success, False otherwise. """ info('AddSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorAdd = {} if name: sensorAdd['name'] = name if device: sensorAdd['device'] = device if args: sensorAdd['args'] = args if description: sensorAdd['description'] = description with self.sensorMutex: retValue = manager.addDeviceJSON(sensorAdd) self.InitCallbacks() info('Add device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except Exception: exception('Error adding sensor') bVal = False return bVal def EditSensor(self, name, description, device, args): """Edit an existing sensor/actuator Args: name: Name of sensor to edit description: New sensor description device: New sensor device class args: New sensor specific args Returns: True for success, False otherwise. """ info('EditSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorEdit = {} name = name sensorEdit['name'] = name sensorEdit['device'] = device sensorEdit['description'] = description sensorEdit['args'] = args with self.sensorMutex: retValue = manager.updateDevice(name, sensorEdit) self.InitCallbacks() info('Edit device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except: exception("Edit sensor failed") bVal = False return bVal def RemoveSensor(self, name): """Remove an existing sensor/actuator Args: name: Name of sensor to remove Returns: True for success, False otherwise. """ bVal = False try: if self.pluginManager.is_plugin(name): return self.pluginManager.disable(name) sensorRemove = name try: sensor = instance.deviceInstance(sensorRemove) if hasattr(sensor, 'removeCallback'): sensor.removeCallback() except: pass with self.sensorMutex: retValue = manager.removeDevice(sensorRemove) info('Remove device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except: exception("Remove sensor failed") bVal = False return bVal def EnableSensor(self, sensor, enable): """Enable a sensor/actuator Args: sensor: Hash composed from name and device class/type enable: 1 to enable, 0 to disable Returns: True for success, False otherwise. """ info('Enable sensor: ' + str(sensor) + ' ' + str(enable)) try: if sensor is None: return False if enable is None: return False with self.sensorMutex: if enable == 0: #add item to the list if sensor not in self.disabledSensors: DbManager.Insert(self.disabledSensorTable, sensor) self.disabledSensors[sensor] = 1 else: #remove item from the list if sensor in self.disabledSensors: DbManager.Delete(self.disabledSensorTable, sensor) del self.disabledSensors[sensor] #save list except Exception as ex: error('EnableSensor Failed with exception: ' + str(ex)) return False return True def GpioCommand(self, command, channel, value): """Execute onboard GPIO command Args: command: Type of command to execute channel: GPIO pin value: Value to use for writing data Returns: String containing command specific return value on success, or 'failure' on failure """ info('GpioCommand {}, channel {}, value {}'.format(command, channel, value)) result = 'failure' if command == 'function': old_state = self.gpio.digitalRead(channel) if value.lower() in ('in', 'input'): result = str(self.gpio.setFunctionString(channel, 'in')) elif value.lower() in ('out', 'output'): result = str(self.gpio.setFunctionString(channel, 'out')) new_state = self.gpio.digitalRead(channel) if new_state != old_state: self.OnGpioStateChange(channel, new_state) elif command in ('value', ''): return self.gpio.digitalWrite(channel, int(value)) debug('GPIO command failed') return result def SensorCommand(self, command, sensorId, channel, value): """Execute sensor/actuator command Args: command: Type of command to execute sensorId: Sensor id channel: Pin/channel on device, None if there is no channel value: Value to use for setting the sensor state Returns: Command specific return value on success, False on failure """ result = False info('SensorCommand: {}, sensor {}, channel {}, value {}'.format(command, sensorId, channel, value)) try: if self.pluginManager.is_plugin(sensorId, channel): return self.pluginManager.write_value(sensorId, channel, value) commands = {'integer': {'function': 'write', 'value_type': int}, 'value': {'function': 'write', 'value_type': int}, 'function': {'function': 'setFunctionString', 'value_type': str}, 'angle': {'function': 'writeAngle', 'value_type': float}, 'float': {'function': 'writeFloat', 'value_type': float}, 'volt': {'function': 'writeVolt', 'value_type': float}} with self.sensorMutex: if sensorId in self.disabledSensors: info('Sensor disabled') return result sensor = instance.deviceInstance(sensorId) if not sensor: info('Sensor not found') return result if command in commands: device = instance.DEVICES[sensorId] info('Sensor found: {}'.format(device)) func = getattr(sensor, commands[command]['function']) value = commands[command]['value_type'](value) if channel: result = self.CallDeviceFunction(func, int(channel), value) else: result = self.CallDeviceFunction(func, value) if 'DigitalActuator' in device['type']: manager.updateDeviceState(sensorId, value) return result warn('Command not implemented: {}'.format(command)) return result except Exception: exception('SensorCommand failed') return result
class SensorsClient(): """Class for interfacing with sensors and actuators""" def __init__(self): """Initialize the bus and sensor info and start monitoring sensor states""" self.sensorMutex = RLock() self.exiting = Event() self.onDataChanged = None self.onSystemInfo = None self.systemData = [] self.currentSystemState = [] self.disabledSensors = {} self.disabledSensorTable = "disabled_sensors" checkAllBus() self.gpio = GPIO() manager.addDeviceInstance("GPIO", "GPIO", "GPIO", self.gpio, [], "system") manager.loadJsonDevices("rest") results = DbManager.Select(self.disabledSensorTable) if results: for row in results: self.disabledSensors[row[0]] = 1 self.StartMonitoring() def SetDataChanged(self, onDataChanged=None, onSystemInfo=None): """Set callbacks to call when data has changed Args: onDataChanged: Function to call when sensor data changes onSystemInfo: Function to call when system info changes """ self.onDataChanged = onDataChanged self.onSystemInfo = onSystemInfo def StartMonitoring(self): """Start thread monitoring sensor data""" ThreadPool.Submit(self.Monitor) def StopMonitoring(self): """Stop thread monitoring sensor data""" self.exiting.set() def Monitor(self): """Monitor bus/sensor states and system info and report changed data via callbacks""" debug('Monitoring sensors and os resources started') while not self.exiting.is_set(): try: if not self.exiting.wait(REFRESH_FREQUENCY): self.currentSystemState = [] self.MonitorSystemInformation() self.MonitorSensors() self.MonitorBus() if self.currentSystemState != self.systemData: changedSystemData = self.currentSystemState if self.systemData: changedSystemData = [x for x in self.currentSystemState if x not in self.systemData] if self.onDataChanged and changedSystemData: self.onDataChanged(changedSystemData) self.systemData = self.currentSystemState except: exception('Monitoring sensors and os resources failed') debug('Monitoring sensors and os resources finished') def MonitorSensors(self): """Check sensor states for changes""" if self.exiting.is_set(): return self.currentSystemState += self.SensorsInfo() def MonitorBus(self): """Check bus states for changes""" if self.exiting.is_set(): return self.currentSystemState += self.BusInfo() def MonitorSystemInformation(self): """Check system info for changes""" if self.exiting.is_set(): return self.currentSystemState += self.SystemInformation() def SystemInformation(self): """Return dict containing current system info, including CPU, RAM, storage and network info""" newSystemInfo = [] try: systemInfo = SystemInfo() newSystemInfo = systemInfo.getSystemInformation() except Exception: exception('SystemInformation failed') return newSystemInfo def CallDeviceFunction(self, func, *args): """Call a function for a sensor/actuator device and format the result value type Args: func: Function to call args: Parameters to pass to the function Returns: True for success, False otherwise. """ result = func(*args) if result != None: if hasattr(func, "contentType"): if func.contentType != M_JSON: value_type = type(result) response = value_type(func.format % result) else: response = result else: response = result return response def BusInfo(self): """Return a dict with current bus info""" bus_info = [] gpio_state = self.gpio.wildcard() for key, value in gpio_state.items(): cayennemqtt.DataChannel.add(bus_info, cayennemqtt.SYS_GPIO, key, cayennemqtt.VALUE, value['value']) cayennemqtt.DataChannel.add(bus_info, cayennemqtt.SYS_GPIO, key, cayennemqtt.FUNCTION, value['function']) return bus_info def SensorsInfo(self): """Return a list with current sensor states for all enabled sensors""" manager.deviceDetector() devices = manager.getDeviceList() sensors_info = [] if devices is None: return sensors_info for device in devices: sensor = instance.deviceInstance(device['name']) if 'enabled' not in device or device['enabled'] == 1: sensor_types = {'Temperature': {'function': 'getCelsius', 'data_args': {'type': 'temp', 'unit': 'c'}}, 'Humidity': {'function': 'getHumidityPercent', 'data_args': {'type': 'rel_hum', 'unit': 'p'}}, 'Pressure': {'function': 'getPascal', 'data_args': {'type': 'bp', 'unit': 'pa'}}, 'Luminosity': {'function': 'getLux', 'data_args': {'type': 'lum', 'unit': 'lux'}}, 'Distance': {'function': 'getCentimeter', 'data_args': {'type': 'prox', 'unit': 'cm'}}, 'ServoMotor': {'function': 'readAngle', 'data_args': {'type': 'analog_actuator'}}, 'DigitalSensor': {'function': 'read', 'data_args': {'type': 'digital_sensor', 'unit': 'd'}}, 'DigitalActuator': {'function': 'read', 'data_args': {'type': 'digital_actuator', 'unit': 'd'}}, 'AnalogSensor': {'function': 'readFloat', 'data_args': {'type': 'analog_sensor'}}, 'AnalogActuator': {'function': 'readFloat', 'data_args': {'type': 'analog_actuator'}}} extension_types = {'ADC': {'function': 'analogReadAllFloat'}, 'DAC': {'function': 'analogReadAllFloat'}, 'PWM': {'function': 'pwmWildcard'}, 'GPIOPort': {'function': 'wildcard'}} for device_type in device['type']: try: display_name = device['description'] except: display_name = None if device_type in sensor_types: try: sensor_type = sensor_types[device_type] func = getattr(sensor, sensor_type['function']) if len(device['type']) > 1: channel = '{}:{}'.format(device['name'], device_type.lower()) else: channel = device['name'] cayennemqtt.DataChannel.add(sensors_info, cayennemqtt.DEV_SENSOR, channel, value=self.CallDeviceFunction(func), name=display_name, **sensor_type['data_args']) except: exception('Failed to get sensor data: {} {}'.format(device_type, device['name'])) else: try: extension_type = extension_types[device_type] func = getattr(sensor, extension_type['function']) values = self.CallDeviceFunction(func) for pin, value in values.items(): cayennemqtt.DataChannel.add(sensors_info, cayennemqtt.DEV_SENSOR, device['name'] + ':' + str(pin), cayennemqtt.VALUE, value, name=display_name) except: exception('Failed to get extension data: {} {}'.format(device_type, device['name'])) logJson('Sensors info: {}'.format(sensors_info)) return sensors_info def AddSensor(self, name, description, device, args): """Add a new sensor/actuator Args: name: Name of sensor to add description: Sensor description device: Sensor device class args: Sensor specific args Returns: True for success, False otherwise. """ info('AddSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorAdd = {} if name: sensorAdd['name'] = name if device: sensorAdd['device'] = device if args: sensorAdd['args'] = args if description: sensorAdd['description'] = description with self.sensorMutex: retValue = manager.addDeviceJSON(sensorAdd) info('Add device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except: bVal = False return bVal def EditSensor(self, name, description, device, args): """Edit an existing sensor/actuator Args: name: Name of sensor to edit description: New sensor description device: New sensor device class args: New sensor specific args Returns: True for success, False otherwise. """ info('EditSensor: {}, {}, {}, {}'.format(name, description, device, args)) bVal = False try: sensorEdit = {} name = name sensorEdit['name'] = name sensorEdit['device'] = device sensorEdit['description'] = description sensorEdit['args'] = args with self.sensorMutex: retValue = manager.updateDevice(name, sensorEdit) info('Edit device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except: exception("Edit sensor failed") bVal = False return bVal def RemoveSensor(self, name): """Remove an existing sensor/actuator Args: name: Name of sensor to remove Returns: True for success, False otherwise. """ bVal = False try: sensorRemove = name with self.sensorMutex: retValue = manager.removeDevice(sensorRemove) info('Remove device returned: {}'.format(retValue)) if retValue[0] == 200: bVal = True except: exception("Remove sensor failed") bVal = False return bVal def EnableSensor(self, sensor, enable): """Enable a sensor/actuator Args: sensor: Hash composed from name and device class/type enable: 1 to enable, 0 to disable Returns: True for success, False otherwise. """ info('Enable sensor: ' + str(sensor) + ' ' + str(enable)) try: if sensor is None: return False if enable is None: return False with self.sensorMutex: if enable == 0: #add item to the list if sensor not in self.disabledSensors: rowId = DbManager.Insert(self.disabledSensorTable, sensor) self.disabledSensors[sensor] = 1 else: #remove item from the list if sensor in self.disabledSensors: DbManager.Delete(self.disabledSensorTable, sensor) del self.disabledSensors[sensor] #save list except Exception as ex: error('EnableSensor Failed with exception: ' + str(ex)) return False self.AddRefresh() return True def GpioCommand(self, command, channel, value): """Execute onboard GPIO command Args: command: Type of command to execute channel: GPIO pin value: Value to use for writing data Returns: String containing command specific return value on success, or 'failure' on failure """ info('GpioCommand {}, channel {}, value {}'.format(command, channel, value)) if command == 'function': if value.lower() in ('in', 'input'): return str(self.gpio.setFunctionString(channel, 'in')) elif value.lower() in ('out', 'output'): return str(self.gpio.setFunctionString(channel, 'out')) elif command in ('value', ''): return self.gpio.digitalWrite(channel, int(value)) debug('GPIO command failed') return 'failure' def SensorCommand(self, command, sensorId, channel, value): """Execute sensor/actuator command Args: command: Type of command to execute sensorId: Sensor id channel: Pin/channel on device, None if there is no channel value: Value to use for setting the sensor state Returns: Command specific return value on success, False on failure """ result = False info('SensorCommand: {}, sensor {}, channel {}, value {}'.format(command, sensorId, channel, value)) try: commands = {'integer': {'function': 'write', 'value_type': int}, 'value': {'function': 'write', 'value_type': int}, 'function': {'function': 'setFunctionString', 'value_type': str}, 'angle': {'function': 'writeAngle', 'value_type': float}, 'float': {'function': 'writeFloat', 'value_type': float}, 'volt': {'function': 'writeVolt', 'value_type': float}} with self.sensorMutex: if sensorId in self.disabledSensors: info('Sensor disabled') return result sensor = instance.deviceInstance(sensorId) if not sensor: info('Sensor not found') return result if command in commands: info('Sensor found: {}'.format(instance.DEVICES[sensorId])) func = getattr(sensor, commands[command]['function']) value = commands[command]['value_type'](value) if channel: result = self.CallDeviceFunction(func, int(channel), value) else: result = self.CallDeviceFunction(func, value) return result warn('Command not implemented: {}'.format(command)) return result except Exception: exception('SensorCommand failed') return result
""" This script reads GPIO info. It is intended to be launched via sudo in order to read data from files that require root access so the main agent code can run from a non-root process and only elevate to root when necessary. """ import sys # from myDevices.utils.logger import setInfo, info, error, logToFile from myDevices.devices.digital.gpio import NativeGPIO if __name__ == '__main__': # Read data using script so it can be called via sudo, sends the data to the main process by writing to stdout # setInfo() # logToFile() i = 1 while i < len(sys.argv): if sys.argv[i] in ['-p', '--pins']: import json gpio = NativeGPIO() print(json.dumps(gpio.wildcard())) if sys.argv[i] in ['-c', '--channel']: gpio = NativeGPIO() i += 1 channel = int(sys.argv[i]) print(gpio.getFunction(channel)) i += 1