def create_job(self, schedule_item): """Create a job to run a scheduled item schedule_item: the item containing the event to be run at the scheduled time""" debug('Create job: {}'.format(schedule_item)) try: with self.mutex: config = schedule_item['event']['config'] if config['type'] == 'date': schedule_item['job'] = schedule.once().at(config['start_date']) if config['type'] == 'interval': if config['unit'] == 'hour': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).hours if config['unit'] == 'minute': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).minutes if config['unit'] == 'day': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).days.at(config['start_date']) if config['unit'] == 'week': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).weeks.at(config['start_date']) if config['unit'] == 'month': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).months.at(config['start_date']) if config['unit'] == 'year': schedule_item['job'] = schedule.every(config['interval'], config['start_date']).years.at(config['start_date']) if 'last_run' in schedule_item['event']: schedule_item['job'].set_last_run(schedule_item['event']['last_run']) schedule_item['job'].do(self.run_scheduled_item, schedule_item) except: exception('Failed setting up scheduler') return False return True
def add_scheduled_event(self, event, insert = False): """Add a scheduled event to run via the scheduler event: the scheduled event to add insert: if True add the event to the database, otherwise just add it to the running scheduler""" debug('Add scheduled event') result = False try: if event['id'] is None: raise ValueError('No id specified for scheduled event: {}'.format(event)) schedule_item = {'event': event, 'job': None} with self.mutex: try: if event['id'] not in self.schedule_items: if insert == True: self.add_database_record(event['id'], event) result = self.create_job(schedule_item) if result == True: self.schedule_items[event['id']] = schedule_item else: result = self.update_scheduled_event(event) except: exception('Error adding scheduled event') except: exception('Failed to add scheduled event') return result
def message_callback(self, client, userdata, msg): """The callback for when a message is received from the server. client is the client instance for this callback. userdata is the private user data as set in Client() or userdata_set(). msg is the received message. """ try: message = {} if msg.topic[-len(COMMAND_JSON_TOPIC):] == COMMAND_JSON_TOPIC: payload = loads(msg.payload.decode()) message['payload'] = payload['value'] message['cmdId'] = payload['cmdId'] channel = payload['channel'].split('/')[-1].split(';') else: payload = msg.payload.decode().split(',') if len(payload) > 1: message['cmdId'] = payload[0] message['payload'] = payload[1] else: message['payload'] = payload[0] channel = msg.topic.split('/')[-1].split(';') message['channel'] = channel[0] if len(channel) > 1: message['suffix'] = channel[1] debug('message_callback: {}'.format(message)) if self.on_message: self.on_message(message) except: exception('Error processing message: {} {}'.format( msg.topic, str(msg.payload)))
def __init__(self): self.Revision = "0" try: with open('/proc/cpuinfo', 'r') as f: for line in f: splitLine = line.split(':') if len(splitLine) < 2: continue key = splitLine[0].strip() value = splitLine[1].strip() if key == 'Revision': self.Revision = value except: exception("Error reading cpuinfo") self.model = {} self.model["Beta"] = "Model B (Beta)" self.model["000d"] = self.model["000e"] = self.model[ "000f"] = self.model["0002"] = self.model["0003"] = self.model[ "0004"] = self.model["0005"] = self.model["0006"] = "Model B" self.model["0007"] = self.model["0008"] = self.model[ "0009"] = "Model A" self.model["0010"] = "Model B+" self.model["0011"] = "Compute Module" self.model["0012"] = "Model A+" self.model["0013"] = "Model B+" self.model["a01041"] = "Pi 2 Model B" self.model["a21041"] = "Pi 2 Model B" self.model["900092"] = "Zero" self.model["a22082"] = self.model["a02082"] = "Pi 3 Model B"
def run_with_except_hook(*args, **kw): try: run_original(*args, **kw) except (KeyboardInterrupt, SystemExit): raise except: exception('Uncaught exception in thread ' + self.name)
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 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 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 GetHistoricalData(self): data = [] try: if (any(item in argv for item in ['-t', '--test'])): #In debug mode use test data if it is available with open('/etc/myDevices/history_test.json', encoding='utf-8') as data_file: data = loads(data_file.read()) if data: rename('/etc/myDevices/history_test.json', '/etc/myDevices/history_test.json.sent') return data except: pass if self.DataReady(): try: for interval in (History.HOUR, History.DAY, History.WEEK, History.MONTH, History.YEAR): avg = self.GetIntervalAverage(interval) if avg: data.append(avg) return data except: exception('Error getting historical data') return data
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 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 run(self): """Send messages to the server until the thread is stopped""" debug('WriterThread run') while self.Continue: try: if self.cloudClient.exiting.wait(GENERAL_SLEEP_THREAD): return if self.cloudClient.mqttClient.connected == False: info('WriterThread mqttClient not connected') continue got_packet = False topic, message = self.cloudClient.DequeuePacket() if topic or message: got_packet = True try: if message or topic == cayennemqtt.JOBS_TOPIC: # debug('WriterThread, topic: {} {}'.format(topic, message)) if not isinstance(message, str): message = dumps(message) self.cloudClient.mqttClient.publish_packet( topic, message) message = None except: exception("WriterThread publish packet error") finally: if got_packet: self.cloudClient.writeQueue.task_done() except: exception("WriterThread unexpected error") return
def Run(self): """Get running process info""" debug('') try: running_processes = [] with self.mutex: for p in process_iter(): running_processes.append(p.pid) try: if p.pid not in self.mapProcesses or self.mapProcesses[ p.pid].Name != p.name: processInfo = ProcessInfo() processInfo.Pid = p.pid processInfo.Name = p.name() if callable( p.name) else p.name processInfo.Username = p.username() if callable( p.username) else p.username processInfo.Cmdline = p.cmdline() if callable( p.cmdline) else p.cmdline self.mapProcesses[p.pid] = processInfo except Exception: pass remove = [ key for key in self.mapProcesses.keys() if key not in running_processes ] for key in remove: del self.mapProcesses[key] debug('ProcessManager::Run retrieved {} processes'.format( len(self.mapProcesses))) except: exception('ProcessManager::Run failed') debug('ProcessManager::Run retrieved {} processes'.format( len(self.mapProcesses)))
def RefreshProcessManager(self): """Refresh processor usage and memory info""" try: if self.VisibleMemory: del self.VisibleMemory self.VisibleMemory = None memory = virtual_memory() self.VisibleMemory = memory.total if self.AvailableMemory: del self.AvailableMemory self.AvailableMemory = None self.AvailableMemory = memory.available del memory if self.PercentProcessorTime: del self.PercentProcessorTime self.PercentProcessorTime = None self.PercentProcessorTime = cpu_percent() self.totalMemoryCount += 1 self.totalProcessorCount += 1 self.AverageProcessorUsage = ( self.AverageProcessorUsage * (self.totalProcessorCount - 1) + self.PercentProcessorTime) / self.totalProcessorCount if self.PeakProcessorUsage < self.PercentProcessorTime: self.PeakProcessorUsage = self.PercentProcessorTime self.AverageMemoryUsage = ( self.AverageMemoryUsage * (self.totalMemoryCount - 1) + self.AvailableMemory) / self.totalMemoryCount if self.PeakMemoryUsage < self.AvailableMemory: self.PeakMemoryUsage = self.AvailableMemory except: exception('ProcessManager::RefreshProcessManager failed')
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 sendRequest(self, method, uri, body=None): if self.session is not None: headers = {} request_url = self.host + uri future = None self.session.headers['Content-Type'] = 'application/json' self.session.headers['Accept'] = 'application/json' if self.auth is not None: self.session.headers['Authorization'] = self.auth try: if method == 'GET': future = self.session.get(request_url) if method == 'POST': future = self.session.post(request_url, data=body) if method == 'PUT': future = self.session.put(request_url, data=body) if method == 'DELETE': future = self.session.delete(request_url) except Exception as ex: error('sendRequest exception: ' + str(ex)) return None try: response = future.result() except: return None return response exception("No data received")
def AddScheduledItem(self, jsonData, insert=False): #add schedule to both memory and db debug('') retVal = False try: scheduleItem = ScheduleItem(jsonData) if scheduleItem.id is None: raise ValueError( 'No id specified for scheduled item: {}'.format(jsonData)) with self.mutex: try: if scheduleItem.id not in self.schedules: if insert == True: self.AddDbItem(scheduleItem.id, ToJson(jsonData)) info('Setup item: ' + str(scheduleItem.to_dict())) retVal = self.Setup(scheduleItem) if retVal == True: self.schedules[scheduleItem.id] = scheduleItem else: retVal = self.UpdateScheduledItem(jsonData) except: exception('Error adding scheduled item') except: exception('AddScheduledItem Failed') return retVal
def getConfig(): configItem = {} try: (returnCode, output) = RaspiConfig.ExecuteConfigCommand(17, '') if output: print('output: ' + output) values = output.strip().split(' ') configItem['Camera'] = {} for i in values: val1 = i.split('=') configItem['Camera'][val1[0]] = int(val1[1]) del output except: exception('Camera config') try: (returnCode, output) = RaspiConfig.ExecuteConfigCommand(10, '') if output: print('output: ' + output) configItem['DeviceTree'] = int(output.strip()) del output (returnCode, output) = RaspiConfig.ExecuteConfigCommand(18, '') if output: print('output: ' + output) configItem['Serial'] = int(output.strip()) del output (returnCode, output) = RaspiConfig.ExecuteConfigCommand(20, '') if output: print('output: ' + output) configItem['OneWire'] = int(output.strip()) del output except: exception('Camera config') return configItem
def getSystemInformation(): currentSystemInfo = "{}" try: debug('Child process for systeminformation pid:' + str(getpid())) libSystemInformation = CDLL( "/etc/myDevices/libs/libSystemInformation.so") if libSystemInformation: libSystemInformation.GetSystemInformation.restype = c_char_p currentSystemInfo = libSystemInformation.GetSystemInformation( ).decode('utf-8') libSystemInformation.FreeSystemInformation() del libSystemInformation libSystemInformation = None memory = virtual_memory() try: system_info = loads(currentSystemInfo) system_info['Memory']['free'] = memory.available system_info['Memory'][ 'used'] = system_info['Memory']['total'] - memory.available currentSystemInfo = dumps(system_info) except: pass except Exception as ex: exception('getSystemInformation failed to retrieve: ' + str(ex)) finally: return currentSystemInfo
def getCpuInfo(self): """Get CPU information as a list formatted for Cayenne MQTT Returned list example:: [{ 'channel': 'sys:cpu;load', 'value': 12.8, 'type': 'cpuload', 'unit': 'p' }, { 'channel': 'sys:cpu;temp', 'value': 50.843, 'type': 'temp', 'unit': 'c' }] """ cpu_info = [] try: cayennemqtt.DataChannel.add(cpu_info, cayennemqtt.SYS_CPU, suffix=cayennemqtt.LOAD, value=psutil.cpu_percent(1), type='cpuload', unit='p') cayennemqtt.DataChannel.add(cpu_info, cayennemqtt.SYS_CPU, suffix=cayennemqtt.TEMPERATURE, value=CpuInfo.get_cpu_temp(), type='temp', unit='c') except: exception('Error getting CPU info') return cpu_info
def getDiskInfo(self, types): """Get disk information as a list formatted for Cayenne MQTT Args: types: Iterable containing types of disk info to retrieve matching cayennemqtt suffixes, e.g. cayennemqtt.USAGE Returned list example:: [{ 'channel': 'sys:storage:/;capacity', 'value': 13646516224, 'type': 'memory', 'type': 'b' }, { 'channel': 'sys:storage:/;usage', 'value': 6353821696, 'type': 'memory', 'type': 'b' }, { 'channel': 'sys:storage:/mnt/cdrom;capacity', 'value': 479383552, 'type': 'memory', 'type': 'b' }, { 'channel': 'sys:storage:/mnt/cdrom;usage', 'value': 0, 'type': 'memory', 'type': 'b' }] """ storage_info = [] try: for partition in psutil.disk_partitions(True): try: if partition.mountpoint == '/': usage = psutil.disk_usage(partition.mountpoint) if usage.total: if not types or cayennemqtt.USAGE in types: cayennemqtt.DataChannel.add( storage_info, cayennemqtt.SYS_STORAGE, partition.mountpoint, cayennemqtt.USAGE, usage.used, type='memory', unit='b') if not types or cayennemqtt.CAPACITY in types: cayennemqtt.DataChannel.add( storage_info, cayennemqtt.SYS_STORAGE, partition.mountpoint, cayennemqtt.CAPACITY, usage.total, type='memory', unit='b') except: pass except: exception('Error getting disk info') return storage_info
def run(self): """Send messages to the server until the thread is stopped""" debug('WriterThread run') while self.Continue: try: if self.cloudClient.exiting.wait(GENERAL_SLEEP_THREAD): return if self.cloudClient.mqttClient.connected == False: info('WriterThread mqttClient not connected') continue got_packet = False topic, message = self.cloudClient.DequeuePacket() info("topic={}, message={}".format(topic, message)) # startswith(cayennemqtt.DEV_SENSOR) if topic or message: got_packet = True try: if message or topic == cayennemqtt.JOBS_TOPIC: if topic == cayennemqtt.DATA_TOPIC: for sensor in message: if sensor['channel'].startswith( cayennemqtt.DEV_SENSOR): # "state_topic": "{}/sensor/{}/dev:{}/state".format(self.mqtt_dis_prefix, self.serial, name ), state_topic = "sensor/{}/{}/state".format( self.cloudClient.hardware.Serial, sensor['channel']) sensor_message = { "domain": 'sensor', "device_class": sensor['type'], "location": "", 'value': sensor['value'] } sensor_message = dumps(sensor_message) info("state_topic={} ,sensor_message={}". format(state_topic, sensor_message)) self.cloudClient.mqttClient.publish_packet( state_topic, sensor_message) continue elif sensor['channel'].startswith( cayennemqtt.SYS_GPIO): info("sys.gpio={} ".format(sensor)) elif sensor['channel'].startswith("sys"): info("sys={} ".format(sensor)) if not isinstance(message, str): message = dumps(message) self.cloudClient.mqttClient.publish_packet( topic, message) message = None except: exception("WriterThread publish packet error") finally: if got_packet: self.cloudClient.writeQueue.task_done() except: exception("WriterThread unexpected error") return
def ToJson(object): returnValue = "{}" try: import jsonpickle returnValue = jsonpickle.encode(object) except: exception('Json encoding failed') return returnValue
def ToJson(object): returnValue = "{}" try: returnValue = encode(object, unpicklable=False, make_refs=False) except: exception('ToJson Failed') return returnValue
def run(self): sleep(self.initial_delay) while True: try: self.function() sleep(self.interval + GENERAL_SLEEP_THREAD) except: exception("TimerThread Unexpected error")
def CheckVersion(self, currentVersion, newVersion): debug('') bVal = False try: bVal = LooseVersion(currentVersion) < LooseVersion(newVersion) except: exception('CheckVersion failed') return bVal
def GetIpAddress(self, interface): ip_addr = None try: from netifaces import AF_INET, AF_INET6, ifaddresses ip_addr = ifaddresses(interface)[AF_INET][0]['addr'] except: exception('GetIpAddress failed') return ip_addr
def Search(self, interface): if interface in self.wirelessModules: try: from iwlib import iwlist endpoints = iwlist.scan(interface) return endpoints except: exception('Wifi search address') return None
def Restart(): try: info('Daemon Restarting myDevices' ) (output, returncode) = ServiceManager.ExecuteCommand('sudo service myDevices restart') debug(str(output) + ' ' + str(returncode)) del output except: exception ("Daemon::Restart Unexpected error") Daemon.Exit()