def CreateTable(tablename, columns, required_columns=None): try: with mutex: if not cursor or not connection: return False if required_columns and len(required_columns): cursor.execute('PRAGMA table_info(' + tablename + ')') actual_columns = [ column[1] for column in cursor.fetchall() ] if actual_columns != required_columns: try: if actual_columns: warn( tablename + ' table columns {} do not match required columns {}, dropping table' .format(actual_columns, required_columns) + " From: " + str(hex(id(connection))) + " " + str(hex(id(cursor)))) cursor.execute('DROP TABLE ' + tablename) connection.commit() except: pass del actual_columns cursor.execute('CREATE TABLE IF NOT EXISTS ' + tablename + ' (' + str(columns) + ')') connection.commit() # sleep(5) except Exception as ex: error("Failed to CreateTable: " + tablename + " " + str(ex)) return False return True
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 ProcessPowerCommand(self, message): """Process command to reboot/shutdown the system Returns: True if command was processed, False otherwise.""" error_message = None try: self.EnqueueCommandResponse(message, error_message) commands = { cayennemqtt.SYS_POWER_RESET: 'sudo shutdown -r now', cayennemqtt.SYS_POWER_HALT: 'sudo shutdown -h now' } if int(message['payload']) == 1: debug('Processing power command') data = [] cayennemqtt.DataChannel.add(data, message['channel'], value=1) self.EnqueuePacket(data) self.writeQueue.join() info('Calling execute: {}'.format( commands[message['channel']])) output, result = executeCommand(commands[message['channel']]) debug('ProcessPowerCommand: {}, result: {}, output: {}'.format( message, result, output)) if result != 0: error_message = 'Error executing shutdown command' except Exception as ex: error_message = '{}: {}'.format(type(ex).__name__, ex) if error_message: error(error_message) data = [] cayennemqtt.DataChannel.add(data, message['channel'], value=0) self.EnqueuePacket(data) raise ExecuteMessageError(error_message) return error_message == None
def addDevice(name, device, description, args, origin): if name in DEVICES: logger.error("Device <%s> already exists" % name) return -1 logger.debug('addDevice: ' + str(name) + ' ' + str(device)) # if '/' in device: # deviceClass = device.split('/')[0] # else: # deviceClass = device try: constructor = findDeviceClass(device) except Exception as ex: logger.debug('findDeviceClass failure:' + str(ex)) return 0 logger.debug('constructor class found ' + str(constructor)) if constructor == None: raise Exception("Device driver not found for %s" % device) instance = None try: if len(args) > 0: instance = constructor(**args) else: instance = constructor() logger.debug('Adding instance ' + str(instance)) addDeviceInstance(name, device, description, instance, args, origin) return 1 except Exception as e: logger.error("Error while adding device %s(%s) : %s" % (name, device, e)) # addDeviceInstance(name, device, description, None, args, origin) removeDevice(name) return 0
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 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 writeByte(self, value): try: info('DS2408 writeByte {} {} {}'.format(self.slave, value, bytearray([value]))) command = 'sudo python3 -m myDevices.devices.writevalue /sys/bus/w1/devices/{}/output {}'.format(self.slave, value) subprocess.call(command.split()) except Exception as ex: error('DS2408 writeByte error: {}'.format(ex))
def __init__(self): self.setPinMapping() GPIOPort.__init__(self, max(self.pins) + 1) self.post_value = True self.post_function = True self.gpio_setup = [] self.gpio_reset = [] self.gpio_map = None self.pinFunctionSet = set() self.valueFile = {pin: None for pin in self.pins} self.functionFile = {pin: None for pin in self.pins} for pin in self.pins: # Export the pins here to prevent a delay when accessing the values for the # first time while waiting for the file group to be set self.__checkFilesystemExport__(pin) if gpio_library: gpio_library.setmode(gpio_library.ASUS) else: try: with open('/dev/gpiomem', 'rb') as gpiomem: self.gpio_map = mmap.mmap(gpiomem.fileno(), BLOCK_SIZE, prot=mmap.PROT_READ) except FileNotFoundError: pass except OSError as err: error(err)
def __init__(self): self.setPinMapping() GPIOPort.__init__(self, max(self.pins) + 1) self.post_value = True self.post_function = True self.gpio_setup = [] self.gpio_reset = [] self.gpio_map = None self.pinFunctionSet = set() self.valueFile = {pin:None for pin in self.pins} self.functionFile = {pin:None for pin in self.pins} self.callbacks = {} self.edge_poll = select.epoll() thread = Thread(target=self.pollEdges, daemon=True) thread.start() for pin in self.pins: # Export the pins here to prevent a delay when accessing the values for the # first time while waiting for the file group to be set self.__checkFilesystemExport__(pin) if gpio_library: gpio_library.setmode(gpio_library.ASUS) elif not Hardware().isRaspberryPi3(): # On the Pi 3 the memory mapped /dev/gpiomem file seems to give strange, inconsistent readings, like duplicated # 4 byte sequences and "oipg" ASCII values. This might be some issue with the way Python mmap works since it didn't # seem to happen with the wiringPi C library using uint32_t pointers. For now we just avoid using /dev/gpiomem on Pi 3. try: with open('/dev/gpiomem', 'rb') as gpiomem: self.gpio_map = mmap.mmap(gpiomem.fileno(), BLOCK_SIZE, prot=mmap.PROT_READ) except FileNotFoundError: pass except OSError as err: error(err)
def Start(self): #debug('Start') if self.connected: ret = False error('Start already connected') else: info('Connecting to: {}:{}'.format(self.HOST, self.PORT)) count = 0 with self.mutex: count += 1 while self.connected == False and count < 30: try: self.sock = None self.wrappedSocket = None ##debug('Start wrap_socket') self.sock = socket(AF_INET, SOCK_STREAM) #self.wrappedSocket = wrap_socket(self.sock, ca_certs="/etc/myDevices/ca.crt", cert_reqs=CERT_REQUIRED) self.wrappedSocket = wrap_socket(self.sock) self.wrappedSocket.connect((self.HOST, self.PORT)) info('myDevices cloud connected') self.connected = True except socket_error as serr: Daemon.OnFailure('cloud', serr.errno) error('Start failed: ' + str(self.HOST) + ':' + str(self.PORT) + ' Error:' + str(serr)) self.connected = False sleep(30 - count) return self.connected
def exceptionHook(exc_type, exc_value, exc_traceback): """Make sure any uncaught exceptions are logged""" debug('Daemon::exceptionHook ') if issubclass(exc_type, KeyboardInterrupt): __excepthook__(exc_type, exc_value, exc_traceback) return error("Uncaught exception", exc_info=(exc_type, exc_value, exc_traceback))
def read(self): measure_time = datetime.datetime.now().timestamp() try: range = self.range return RangeResult(self.range_status, range, measure_time) except Exception as e: error(e) return RangeResult(RangeResult.ERR_MISSING_DATA, -1, measure_time)
def readByte(self): try: with open("/sys/bus/w1/devices/%s/output" % self.slave, "rb") as f: data = f.read(1) return bytearray(data)[0] except IOError as ex: error('DS2408 readByte error: {}'.format(ex)) return -1
def pollEdges(self): while True: try: events = self.edge_poll.poll(1) except IOError as e: if e.errno != errno.EINTR: error(e) if len(events) > 0: self.onEdgeEvent(events)
def CheckPT_ACK(self, messageObject): try: packetType = int(messageObject['PacketType']) if packetType == PacketTypes.PT_ACK.value: self.lastPing = time() return True except: debug('') error('CheckPT_ACK failure: ' + str(messageObject)) return False
def MQRead(self, mq_pin): rs = 0.0 if self.adc: for i in range(self.READ_SAMPLE_TIMES): rs += self.MQResistanceCalculation(self.adc.read(mq_pin)) time.sleep(self.READ_SAMPLE_INTERVAL / 1000.0) rs = rs / self.READ_SAMPLE_TIMES else: error("MQRead adc is none") return rs
def readCO2(self): # 模拟电压输出与浓度之间的换算关系,以 0.4V~2.0V 输出范围为例: # Vo(V)=0.4V+(2.0V-0.4V)*C(浓度 ppm) /量程(ppm) vo = 0.0 if self.adc: vo = self.adc.analogReadVolt(self.co2_channel) else: error("adc is None") return int((vo - 0.4) * self.RANGE / (self.VH - self.VL))
def Terminate(self): """Terminate the process""" info('ProcessManager::Terminate Name:' + self.Name + ' PID:' + str(self.Pid)) try: process = Process(self.Pid) process.terminate() except Exception as ex: error('ProcessInfo::Terminate failed Name:' + self.Name + ' PID:' + str(self.Pid) + ' Exception:' + str(ex)) return False return True
def init_sense_hat(self): """Initializes connection to Sense HAT service and gets a SenseHat shared object.""" if not self.sense_hat: try: self.manager = connect_client() self.manager.use_emulator(self.use_emulator) self.sense_hat = self.manager.SenseHat() except ConnectionRefusedError as e: info('Sense HAT service connection refused') error(e) except RemoteError as e: error('Failed to connect to Sense HAT device')
def read(self): measure_time = datetime.datetime.now().timestamp() try: amb_temp = self.get_amb_temp() obj_temp = self.get_obj_temp() return TemperatureResult(TemperatureResult.ERR_NO_ERROR, amb_temp, obj_temp, measure_time) except Exception as e: error(e) return TemperatureResult(TemperatureResult.ERR_MISSING_DATA, -1, -1, measure_time)
def connect_client(): """Connect a client to the sensehat service.""" try: debug('Connecting to sensehat service') SenseHATManager.register('SenseHat') SenseHATManager.register('use_emulator') manager = SenseHATManager(SERVER_ADDRESS, AUTH_KEY) manager.connect() return manager except RemoteError as e: error( 'Error connecting to sensehat service, if using the Sense HAT emulator make sure it is has been launched in the GUI' )
def __setFunction__(self, channel, value): self.__checkFilesystemFunction__(channel) self.checkDigitalChannelExported(channel) self.checkPostingFunctionAllowed() try: if (value == self.IN): self.functionFile[channel].write("in") else: self.functionFile[channel].write("out") self.functionFile[channel].seek(0) except Exception as ex: error('Failed on __setFunction__: ' + str(channel) + ' ' + str(ex)) pass
def RemoveScheduledItemById(self, id): with self.mutex: if id in self.schedules: try: scheduleItem = self.schedules[id] schedule.cancel_job(scheduleItem.job) del self.schedules[id] self.RemoveDbItem(scheduleItem.id) return True except KeyError: warn('RemoveScheduledItem key error: ' + str(Id)) error('RemoveScheduledItem id not found: ' + str(id)) return False
def __init__(self, address=_VL6180X_DEFAULT_I2C_ADDR): try: i2c = busio.I2C(board.SCL, board.SDA) self._device = i2c_device.I2CDevice(i2c, address) if self._read_8(_VL6180X_REG_IDENTIFICATION_MODEL_ID) != 0xB4: raise RuntimeError( 'Could not find VL6180X, is it connected and powered?') self._load_settings() self._write_8(_VL6180X_REG_SYSTEM_FRESH_OUT_OF_RESET, 0x00) except Exception as e: error(e)
def CheckSubscription(self): inviteCode = self.config.get('Agent', 'InviteCode') cayenneApiClient = CayenneApiClient(self.CayenneApiHost) authId = cayenneApiClient.loginDevice(inviteCode) if authId == None: error( 'Registration failed for invite code {}, closing the process'. format(inviteCode)) Daemon.Exit() else: info('Registration succeeded for invite code {}, auth id = {}'. format(inviteCode, authId)) self.config.set('Agent', 'Initialized', 'true') self.MachineId = authId
def Start(self): """Connect to server and start background threads""" try: self.installDate = None try: self.installDate = self.config.get('Agent', 'InstallDate', fallback=None) except: pass if not self.installDate: self.installDate = int(time()) self.config.set('Agent', 'InstallDate', self.installDate) if not self.username and not self.password and not self.clientId: self.CheckSubscription() if not self.Connect(): error('Error starting agent') return self.schedulerEngine = SchedulerEngine(self, 'client_scheduler') self.readQueue = Queue() self.writeQueue = Queue() self.hardware = Hardware() self.oSInfo = OSInfo() self.count = 10000 self.buff = bytearray(self.count) self.writerThread = WriterThread('writer', self) self.writerThread.start() self.processorThread = ProcessorThread('processor', self) self.processorThread.start() self.systemInfo = [] TimerThread(self.SendSystemInfo, 300) self.sensorsClient = sensors.SensorsClient(self) self.sensorsClient.SetDataChanged(self.OnDataChanged) # TimerThread(self.SendSystemState, 30, 5) self.updater = Updater(self.config) self.updater.start() events = self.schedulerEngine.get_scheduled_events() self.EnqueuePacket(events, cayennemqtt.JOBS_TOPIC) # self.sentHistoryData = {} # self.historySendFails = 0 # self.historyThread = Thread(target=self.SendHistoryData) # self.historyThread.setDaemon(True) # self.historyThread.start() except Exception as e: exception('Initialize error: ' + str(e))
def doReadMQ(self): try: read = self.MQRead(self.mq_channel) # info("read mq_channel:{}".format(read)) measure_time = datetime.datetime.now().timestamp() h2s = self.MQGetGasPercentage(read / self.Ro, self.GAS_H2S) # co = self.MQGetGasPercentage(read/self.Ro, self.GAS_CO) # ch4 = self.MQGetGasPercentage(read / self.Ro, self.GAS_CH4) # return MQ136Result(MQ136Result.ERR_NO_ERROR, h2s, co, ch4, measure_time) # info(" h2s ={}".format(h2s)) return h2s except Exception as e: error(e) # return MQ136Result(MQ136Result.ERR_MISSING_DATA, -1, -1, -1,measure_time) return -1
def write_value(self, value, channel, value_type=None): """Write the data value on the specified channel.""" result = None self.set_plugin() if not self.plugin: error('Plugin {} is not loaded'.format(self.plugin_id)) return result self.set_function(channel) try: write_args = self.write_args if value_type: write_args['value_type'] = value_type result = getattr(self.plugin['instance'], self.plugin['write'])(channel, value, **write_args) except Exception as e: error('Error writing value to plugin {}, channel {}: {}'.format(self.plugin_id, channel, e)) return result
def read_value(self, channel, value_type=None): """Read the data value on the specified channel.""" result = None self.set_plugin() if not self.plugin: error('Plugin {} is not loaded'.format(self.plugin_id)) return result self.set_function(channel) try: read_args = self.read_args if value_type: read_args['value_type'] = value_type result = getattr(self.plugin['instance'], self.plugin['read'])(channel, **read_args) except Exception as e: error('Error reading value from plugin {}, channel {}: {}'.format(self.plugin_id, channel, e)) return result
def removeDevice(name): if name in DEVICES: if name in DYNAMIC_DEVICES: if hasattr(DEVICES[name]["device"], 'close'): DEVICES[name]["device"].close() del DEVICES[name] del DYNAMIC_DEVICES[name] json_devices = getJSON(DYNAMIC_DEVICES) with open(DEVICES_JSON_FILE, 'w') as outfile: outfile.write(json_devices) logger.debug("Deleted device %s" % name) return (200, None, None) logger.error("Cannot delete %s, found but not added via REST" % name) return (403, None, None) logger.error("Cannot delete %s, not found" % name) return (404, None, None)