Example #1
0
 def begin(self,
           username,
           password,
           clientid,
           hostname='mqtt.mydevices.com',
           port=8883):
     """Initializes the client and connects to Cayenne.
     
     username is the Cayenne username.
     password is the Cayenne password.
     clientid is the Cayennne client ID for the device.
     hostname is the MQTT broker hostname.
     port is the MQTT broker port.
     """
     self.root_topic = 'v1/{}/things/{}'.format(username, clientid)
     self.client = mqtt.Client(client_id=clientid,
                               clean_session=True,
                               userdata=self)
     self.client.on_connect = self.connect_callback
     self.client.on_disconnect = self.disconnect_callback
     self.client.on_message = self.message_callback
     self.client.username_pw_set(username, password)
     if port != 1883:
         self.client.tls_set(ca_certs='/etc/ssl/certs/ca-certificates.crt',
                             tls_version=PROTOCOL_TLSv1_2)
     self.client.connect(hostname, port, 60)
     info('Connecting to {}:{}'.format(hostname, port))
Example #2
0
    def connect_callback(self, client, userdata, flags, rc):
        """The callback for when the client connects to the server.

        client is the client instance for this callback.
        userdata is the private user data as set in Client() or userdata_set().
        flags are the response flags sent by the broker.
        rc is the connection result.
        """
        if rc != 0:
            # MQTT broker error codes
            broker_errors = {
                1: 'unacceptable protocol version',
                2: 'identifier rejected',
                3: 'server unavailable',
                4: 'bad user name or password',
                5: 'not authorized',
            }
            raise Exception("Connection failed, " +
                            broker_errors.get(rc, "result code " + str(rc)))
        else:
            info("Connected with result code " + str(rc))
            self.connected = True
            # Subscribing in on_connect() means that if we lose the connection and
            # reconnect then subscriptions will be renewed.
            client.subscribe(self.get_topic_string(COMMAND_TOPIC, True))
            client.subscribe(self.get_topic_string(COMMAND_JSON_TOPIC, False))
Example #3
0
    def run(self):
        """Run the job and immediately reschedule it."""
        debug('Run job')
        if self.unit == 'date':
            if self.last_run is not None:
                info('date job can run only once. Last run: ' +
                     str(self.last_run))
                return CancelJob
            now = datetime.utcnow()
            #If more than the grace period has passed since the scheduled start time we cancel the job
            if now > (self.at_time + self.grace_period):
                info('Job scheduled time has passed, job will not be run: ' +
                     str(self.at_time) + ' current time: ' + str(now))
                return CancelJob

        debug('Running job: {}'.format(self))

        if self.end_date is not None:
            if datetime.utcnow() > self.end_date:
                info('Skipping job, end date has passed: ' +
                     str(self.end_date))
                return CancelJob

        ret = self.job_func()
        self.last_run = datetime.utcnow()

        if self.unit == 'date':
            info('Date job finished, it will not be recheduled')
            return CancelJob

        self._schedule_next_run()
        info('Job finished, next run time: ' + str(self.next_run))

        return ret
Example #4
0
 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))
Example #5
0
 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
Example #6
0
 def testSensorsInfo(self):
     debug('testSensorsInfo')
     sensors = SensorsClientTest.client.SensorsInfo()
     info('Sensors info: {}'.format(sensors))
     for sensor in sensors:
         self.assertEqual('dev:', sensor['channel'][:4])
         self.assertIn('value', sensor)
Example #7
0
    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
Example #8
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
Example #9
0
    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
Example #10
0
    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
Example #11
0
 def CalculateAverages(self, current_avgs, new_sample, count, count_sensor):
     info('History CalculateAverages increment: ' + str(count))
     count += 1
     self.CalculateNetworkSpeedAverages(current_avgs, new_sample, count)
     self.CalculateSystemInfoAverages(current_avgs, new_sample, count)
     self.CalculateSensorsInfoAverages(current_avgs, new_sample, count_sensor)
     return count
Example #12
0
    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
Example #13
0
 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
Example #14
0
 def ProcessDeviceCommand(self, message):
     """Process a device command to add/edit/remove a sensor
     
     Returns: True if command was processed, False otherwise."""
     error = None
     try:
         payload = message['payload']
         info('ProcessDeviceCommand payload: {}'.format(payload))
         if message['suffix'] == 'add':
             result = self.sensorsClient.AddSensor(payload['sensorId'],
                                                   payload['description'],
                                                   payload['class'],
                                                   payload['args'])
         elif message['suffix'] == 'edit':
             result = self.sensorsClient.EditSensor(payload['sensorId'],
                                                    payload['description'],
                                                    payload['class'],
                                                    payload['args'])
         elif message['suffix'] == 'delete':
             result = self.sensorsClient.RemoveSensor(payload['sensorId'])
         else:
             error = 'Unknown device command: {}'.format(message['suffix'])
         debug('ProcessDeviceCommand result: {}'.format(result))
         if result is False:
             error = 'Device command failed'
     except Exception as ex:
         error = '{}: {}'.format(type(ex).__name__, ex)
     self.EnqueueCommandResponse(message, error)
     return error == None
Example #15
0
 def testStorageInfo(self):
     storage_info = self.info['Storage']
     info(storage_info)
     self.assertEqual(set(storage_info.keys()), set(('list', )))
     for item in storage_info['list']:
         self.assertLessEqual(set(('device', 'filesystem', 'mount')),
                              set(item.keys()))
Example #16
0
 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'
Example #17
0
 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
Example #18
0
 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
Example #19
0
 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
Example #20
0
def addDeviceJSON(json):
    if "name" in json:
        name = json["name"]
    else:
        name = "%X" % time()
    device = json["device"]

    if 'args' in json:
        args = json["args"]
    else:
        args = {}

    if 'index' in json:
        index = json["index"]
    else:
        index = 99

    if 'description' in json:
        description = json["description"]
    else:
        description = name
    info("{} {} {} {} {} {}".format(name,index, device, description, args, "rest"))
    res = addDevice(name, device, description, args, "rest")
    sleep(0.1)
    logger.debug('Now saving device')
    if res == 1:
        saveDevice(name,  int(time()))
        return (200, "OK", "text/plain")
    elif res == -1:
        return (409, "ALREADY_EXISTS", "text/plain")
    elif res == 0:
        return (500, "ERROR", "text/plain")
Example #21
0
 def ExecuteMessage(self, message):
     """Execute an action described in a message object
     
     Returns: True if action was executed, False otherwise."""
     result = False
     if not message:
         return result
     channel = message['channel']
     info('ExecuteMessage: {}'.format(message))
     if channel in (cayennemqtt.SYS_POWER_RESET,
                    cayennemqtt.SYS_POWER_HALT):
         result = self.ProcessPowerCommand(message)
     elif channel.startswith(cayennemqtt.DEV_SENSOR):
         result = self.ProcessSensorCommand(message)
     elif channel.startswith(cayennemqtt.SYS_GPIO):
         result = self.ProcessGpioCommand(message)
     elif channel == cayennemqtt.AGENT_DEVICES:
         result = self.ProcessDeviceCommand(message)
     elif channel in (cayennemqtt.SYS_I2C, cayennemqtt.SYS_SPI,
                      cayennemqtt.SYS_UART, cayennemqtt.SYS_ONEWIRE):
         result = self.ProcessConfigCommand(message)
     elif channel == cayennemqtt.AGENT_MANAGE:
         result = self.ProcessAgentCommand(message)
     elif channel == cayennemqtt.AGENT_SCHEDULER:
         result = self.ProcessSchedulerCommand(message)
     else:
         info('Unknown message')
     return result
 def write(self, value):
     """Logs the specified value."""
     self.value = value
     if self.digital:
         info('Example actuator digital value: {}'.format(self.value))
     else:
         info('Example actuator analog value: {}'.format(self.value))
Example #23
0
    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
Example #24
0
 def testNetworkInfo(self):
     network_info = self.info['Network']
     info(network_info)
     self.assertGreaterEqual(set(network_info.keys()), set(('list', )))
     for key, value in network_info['list'].items():
         self.assertTrue(value)
         self.assertLessEqual(set(value.keys()), set(('ip', 'ipv6', 'mac')))
     self.assertIsNotNone(network_info['list']['eth0']['ip']['address'])
Example #25
0
def loadModules(bus):
    if BUSLIST[bus]["enabled"] == False and not modulesLoaded(bus):
        info("Loading %s modules" % bus)
        for module in BUSLIST[bus]["modules"]:
            loadModule(module)
        if "wait" in BUSLIST[bus]:
            info("Sleeping %ds to let %s modules load" % (BUSLIST[bus]["wait"], bus))
            time.sleep(BUSLIST[bus]["wait"])
Example #26
0
 def setUp(self):
     setInfo()
     system_info = SystemInfo()
     self.info = {
         item['channel']: item
         for item in system_info.getSystemInformation()
     }
     info(self.info)
Example #27
0
def signal_handler(signal, frame):
    if client:
        if signal == SIGINT:
            info('Program interrupt received, client exiting')
            client.Destroy()
            remove(pidfile)
        else:
            client.Restart()
Example #28
0
def missingOneWireDevice(device):
    if device['class'] in FAMILIES.values() and (
            'slave' not in device['args']
            or not deviceExists(device['args']['slave'])):
        logger.info('1-wire device does not exist: {}, {}'.format(
            device['class'], device['args']['slave']))
        return True
    return False
Example #29
0
    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()
Example #30
0
	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()