示例#1
0
    def disable_210_node_manager_value_to_json(self):
        self.startClient({})
        self.nodeman = JNTNodeMan()
        key = 'test110'
        node = JNTNode(uuid=key,name='Test (%s)'%key, cmd_classes=[0x0000], hadd=HADD%(1000,1000))
        self.nodeman.add_node(node.uuid, node)
        value = JNTValue( uuid='test110_1',
                    help='The test 110_1',
                    units='°C',
                    index=0,
                    cmd_class=0x0000,
                    genre=0x02,
                    type=0x03,
                    get_data_cb=lambda x: 40.14+x,
                    is_writeonly=False,
                    is_polled=True,
                    )
        self.nodeman.add_value_to_node(value.uuid, node, value)
        self.mqtthearbeat = MQTTClient(options={})

        self.nodeman.start(self.mqttc,self.mqtthearbeat, 0.1)
        res = json_loads(value.to_json())
        print res
        self.assertEqual(res['uuid'], 'test110_1')
        self.assertEqual(res['help'], 'The test 110_1')
        self.assertEqual(res['cmd_class'], 0x0000)
        self.assertEqual(res['data'], 40.14)
        self.stopClient()
        self.mqtthearbeat = None
示例#2
0
    def mqtt_on_resolv_hadd(self, client, userdata, message):
        """On resolv hadd message

        :param client: the Client instance that is calling the callback.
        :type client: paho.mqtt.client.Client
        :param userdata: user data of any type and can be set when creating a new client instance or with user_data_set(userdata).
        :type userdata: all
        :param message: The message variable is a MQTTMessage that describes all of the message parameters.
        :type message: paho.mqtt.client.MQTTMessage
        """
        #~ print "mqtt_on_resolv_hadd receive %s"
        logger.debug("mqtt_on_resolv_hadd receive %s", message.payload)
        res = {}
        res['msg_status'] = 200
        data = json_loads(message.payload)
        if 'rep_uuid' not in data:
            logger.debug("mqtt_on_resolv_hadd receive a request with no rep_uuid")
            return
        for ffield in ['add_ctrl', 'add_node']:
            if ffield not in data:
                res['msg_status'] = 400
                res['msg_error'] = "Missing field %s in request" % ffield
        res['rep_uuid'] = data['rep_uuid']
        if res['msg_status'] == 200:
            lease = self.lease_mgr.resolv_hadd(data['add_ctrl'], data['add_node'])
            #print lease
            res.update(lease)
        #print res
        self.publish_reply(uuid=data['rep_uuid'], payload=json_dumps(res))
示例#3
0
    def on_controller_request(self, client, userdata, message):
        """On request

        :param client: the Client instance that is calling the callback.
        :type client: paho.mqtt.client.Client
        :param userdata: user data of any type and can be set when creating a new client instance or with user_data_set(userdata).
        :type userdata: all
        :param message: The message variable is a MQTTMessage that describes all of the message parameters.
        :type message: paho.mqtt.client.MQTTMessage
        """
        logger.debug("on_request receive message %s", message.payload)
        try:
            data = json_loads(message.payload)
            #~ print data['uuid']
            #We should check what value is requested
            #{'hadd', 'cmd_class', 'type'='list', 'genre'='0x04', 'data'='node|value|config', 'uuid'='request_info'}
            if data['cmd_class'] == COMMAND_DISCOVERY:
                if data['genre'] == 0x04:
                    if data['uuid'] in self._requests:
                        resp = {}
                        resp.update(data)
                        try:
                            if message.topic.find('broadcast') != -1:
                                topic = "/broadcast/reply/%s" % data['data']
                                self._requests[data['uuid']](topic, resp)
                            else:
                                topic = "/nodes/%s/reply" % data['data']
                                self._requests[data['uuid']](topic, resp)
                            return
                        except:
                            logger.exception("Exception when running on_request method")
                            return
            logger.warning("Unknown request value %s", data)
        except:
            logger.exception("Exception in on_request")
示例#4
0
    def disable_210_node_manager_value_to_json(self):
        self.startClient({})
        self.nodeman = JNTNodeMan()
        key = "test110"
        node = JNTNode(uuid=key, name="Test (%s)" % key, cmd_classes=[0x0000], hadd=HADD % (1000, 1000))
        self.nodeman.add_node(node.uuid, node)
        value = JNTValue(
            uuid="test110_1",
            help="The test 110_1",
            units="°C",
            index=0,
            cmd_class=0x0000,
            genre=0x02,
            type=0x03,
            get_data_cb=lambda x: 40.14 + x,
            is_writeonly=False,
            is_polled=True,
        )
        self.nodeman.add_value_to_node(value.uuid, node, value)
        self.mqtthearbeat = MQTTClient(options={})

        self.nodeman.start(self.mqttc, self.mqtthearbeat, 0.1)
        res = json_loads(value.to_json())
        print res
        self.assertEqual(res["uuid"], "test110_1")
        self.assertEqual(res["help"], "The test 110_1")
        self.assertEqual(res["cmd_class"], 0x0000)
        self.assertEqual(res["data"], 40.14)
        self.stopClient()
        self.mqtthearbeat = None
示例#5
0
    def on_value(self, client, userdata, message):
        """On value

        Do not lock as it don't add new values to dict. Should be ok using keys instead of iterator.

        :param client: the Client instance that is calling the callback.
        :type client: paho.mqtt.client.Client
        :param userdata: user data of any type and can be set when creating a new client instance or with user_data_set(userdata).
        :type userdata: all
        :param message: The message variable is a MQTTMessage that describes all of the message parameters.
        :type message: paho.mqtt.client.MQTTMessage
        """
        #logger.debug("[%s] - on_value %s", self.__class__.__name__, message.payload)
        try:
            data = json_loads(message.payload)
            if 'genre' in data:
                data = {0:{0:data}}
            elif 'genre' in data[data.keys()[0]]:
                data = {0:data}
            store_index = self.create_store_index()
            for nval in data:
                for kval in data[nval]:
                    if data[nval][kval]['genre'] in [0x02, 0x01]:
                        hadd = data[nval][kval]['hadd']
                        uuid = data[nval][kval]['uuid']
                        index = 0
                        if 'index' in data[nval][kval]:
                            index = data[nval][kval]['index']
                        index = str(index)
                        #~ logger.debug("[%s] - update_last %s,%s,%s : %s", self.__class__.__name__, hadd, value_uuid, value_index)
                        if (hadd, uuid, index) in store_index:
                            self.update_last(hadd, uuid, index, data[nval][kval]['data'])
        except Exception:
            logger.exception("[%s] - Exception in on_value", self.__class__.__name__)
示例#6
0
 def mqtt_on_message(client, userdata, message):
     """On generic message
     """
     msg = json_loads(message.payload)
     print "Received message %s" % msg
     if msg["uuid"] == uuid and msg["hadd"] == node_hadd:
         self.message = message
         self.message_received = True
示例#7
0
    def get_telemetry(self):
        """Roomba method which fetches telemetry data about the robot.

        Other values that can be implemented:

        - sensors['Bumps Wheeldrops'] = self.j['response']['r0']['value']
        - sensors['Wall'] = self.j['response']['r1']['value']
        - sensors['Cliff Left'] = self.j['response']['r2']['value']
        - sensors['Cliff Front Left'] = self.j['response']['r3']['value']
        - sensors['Cliff Front Right'] = self.j['response']['r4']['value']
        - sensors['Cliff Right'] = self.j['response']['r5']['value']
        - sensors['Virtual Wall'] = self.j['response']['r6']['value']
        - sensors['Motor Overcurrents'] = self.j['response']['r7']['value']
        - sensors['Dirt Detector - Left'] = self.j['response']['r8']['value']
        - sensors['Dirt Detector - Right'] = self.j['response']['r9']['value']
        - sensors['Remote Opcode'] = self.j['response']['r10']['value']
        - sensors['Buttons'] = self.j['response']['r11']['value']
        - sensors['Distance'] = self.j['response']['r12']['value']
        - sensors['Angle'] = self.j['response']['r13']['value']
        - sensors['State'] = State[int(self.j['response']['r14']['value'])]
        - sensors['Voltage'] = self.j['response']['r15']['value']
        - sensors['Current'] = self.j['response']['r16']['value']
        - sensors['Temperature'] = self.j['response']['r17']['value']
        - sensors['Charge'] = self.j['response']['r18']['value']
        - sensors['Capacity'] = self.j['response']['r19']['value']
        - sensors['battery-level'] =  int(self.j['response']['r18']['value'])*100 / int (self.j['response']['r19']['value'])
        """
        if self._telemetry_next_run < datetime.now():
            locked = self._lock.acquire(False)
            if locked == True:
                try:
                    auth = (self.values['username'].data, self.values['password'].data)
                    r = requests.get('http://' + self.values['ip_ping_config'].data + '/roomba.json', auth=auth, timeout=self.values['request_timeout'].data)
                    self._telemetry = json_loads(r.text)
                    logger.debug("[%s] - retrieve telemetry : %s", self.__class__.__name__, self._telemetry)
                    self._temperature = float(self._telemetry['response']['r17']['value'])
                    self._charge = float(self._telemetry['response']['r18']['value'])
                    self._capacity = float(self._telemetry['response']['r19']['value'])
                    self._state = int(self._telemetry['response']['r14']['value'])
                    self._voltage = round(float(self._telemetry['response']['r15']['value'])/1000,2)
                    self._current = round(float(self._telemetry['response']['r16']['value']),2)
                    try:
                        self._battery = round(100.0 * self._charge / self._capacity, 2)
                    except ZeroDivisionError:
                        self._battery = -1.0
                    self._telemetry_last = True
                except Exception:
                    logger.exception("[%s] - Exception in get_telemetry", self.__class__.__name__)
                    self._telemetry_last = False
                finally:
                    self._lock.release()
                secs = self.values['ip_ping_poll'].data
                if secs < 0:
                    secs=60
                self._telemetry_next_run = datetime.now() + timedelta(seconds=secs)
示例#8
0
    def assertUpdateValue(
        self,
        type="user",
        data=None,
        cmd_class=0,
        genre=0x04,
        uuid="request_info_nodes",
        node_hadd=None,
        client_hadd=None,
        is_writeonly=False,
        is_readonly=False,
        timeout=5,
    ):
        self.message_received = False
        self.message = None
        print "Waiting for %s : %s" % (node_hadd, uuid)

        def mqtt_on_message(client, userdata, message):
            """On generic message
            """
            msg = json_loads(message.payload)
            print "Received message %s" % msg
            if msg["uuid"] == uuid and msg["hadd"] == node_hadd:
                self.message = message
                self.message_received = True

        self.mqttc.subscribe(topic="/values/%s/%s/#" % (type, node_hadd), callback=mqtt_on_message)
        print "Subscribe to /values/%s/%s/#" % (type, node_hadd)
        time.sleep(0.5)
        msg = {
            "cmd_class": cmd_class,
            "genre": genre,
            "uuid": uuid,
            "reply_hadd": client_hadd,
            "data": data,
            "hadd": node_hadd,
            "is_writeonly": is_writeonly,
            "is_readonly": is_readonly,
        }
        self.mqttc.publish("/nodes/%s/request" % (node_hadd), json_dumps(msg))
        i = 0
        while i < timeout * 10000 and not self.message_received:
            time.sleep(0.0001)
            i += 1
        self.assertTrue(self.message_received)
        self.assertTrue(self.message is not None)
        self.assertTrue(self.message.payload is not None)
        if data is not None:
            msg = json_loads(self.message.payload)
            self.assertEqual(msg["data"], data)
        self.mqttc.unsubscribe(topic="/values/%s/%s/#" % (type, node_hadd))
        time.sleep(0.5)
示例#9
0
 def command(self, command, value=None, args=None):
     """Send command to the roomba 900
     """
     logger.debug("[%s] - Start processing command %s", self.__class__.__name__, command)
     try:
         params = {
             "ip_cloud":self.values['ip_cloud_config'].data,
             "blid":self.values['blid'].data,
             "robotpwd":self.values['robotpwd'].data,
             "command":command,
             "value":value,
         }
         uri = 'https://{ip_cloud}/services/v1/rest/Scripto/execute/AspenApiRequest?blid={blid}&robotpwd={robotpwd}&method={command}'
         if value is not None:
             uri += '&value=%7B%0A%20%20%22remoteCommand%22%20:%20%22{value}%22%0A%7D';
         r = requests.get(uri.format(**params), timeout=self.values['request_timeout'].data)
         ret = json_loads(r.text)
         return ret
     except Exception:
         logger.exception("[%s] - Command %s failed when calling uri %s", self.__class__.__name__, command, uri.format(**params))
示例#10
0
 def on_message(self, client, userdata, message):
     """On generic message
     """
     self.message = message
     self.payload=json_loads(message.payload)
示例#11
0
    def get_telemetry(self):
        """Roomba method which fetches telemetry data about the robot.
        {
            "status": "OK",
            "method": "getStatus",
            "sku": "",
            "country": "",
            "postalCode": "",
            "regDate": "2016-06-23",
            "hardwareVersion": "",
            "manualUpdate": 0.0,
            "swUpdateAvailable": "",
            "schedHold": 0.0,
            "autoEvacCount": "",
            "autoEvacFlags": "",
            "wifiDiagnostics": "",
            "autoEvacModel": "",
            "milestones": "",
            "robotName": "Roomba",
            "robotLanguage": 1.0,
            "tzName": "Europe/Paris",
            "twoPass": 0.0,
            "noAutoPasses": "",
            "openOnly": 0.0,
            "carpetBoost": 0.0,
            "binPause": 1.0,
            "vacHigh": 0.0,
            "noPP": 0.0,
            "ecoCharge": 0.0,
            "mission": "{\"nMssn\":8,\"done\":\"cncl\",\"flags\":32,\"sqft\":0,\"runM\":0,\"chrgM\":0,\"pauseM\":1,\"doneM\":0,\"dirt\":0,\"chrgs\":0,\"saves\":0,\"evacs\":0,\"pauseId\":0,\"wlBars\":[0,0,0,0,0]}",
            "preventativeMaintenance": "[{\"partId\":\"bin\",\"date\":\"2016-06-23\",\"distance\":55,\"runtime\":0,\"months\":0,\"notified\":false},{\"partId\":\"core\",\"date\":\"2016-06-23\",\"distance\":55,\"runtime\":0,\"months\":0,\"notified\":false},{\"partId\":\"extractor\",\"date\":\"2016-06-23\",\"distance\":55,\"runtime\":0,\"months\":0,\"notified\":false}]",
            "cleanSchedule": "{\"cycle\":[\"none\",\"none\",\"none\",\"none\",\"none\",\"none\",\"none\"],\"h\":[0,0,0,0,0,0,0],\"m\":[0,0,0,0,0,0,0]}",
            "robot_status": "{\"flags\":8,\"cycle\":\"quick\",\"phase\":\"run\",\"pos\":{\"theta\":0,\"point\":{\"x\":0,\"y\":0}},\"batPct\":97,\"expireM\":0,\"rechrgM\":0,\"error\":0,\"notReady\":0,\"mssnM\":0,\"sqft\":0}",
            "softwareVersion": "v1.2.9",
            "lastSwUpdate": "2016-06-23 17:55:55+0000",
            "engBuild": "",
            "bbrun": "{\"hr\":0,\"min\":8,\"sqft\":0,\"nStuck\":0,\"nScrubs\":0,\"nPicks\":23,\"nPanics\":0,\"nCliffsF\":24,\"nCliffsR\":34,\"nMBStll\":0,\"nWStll\":0,\"nCBump\":0}",
            "missing": false,
            "ota": "{\"st\":0,\"err\":0,\"lbl\":\"\"}"
        }

        """
        if self._telemetry_next_run < datetime.now():
            locked = self._lock.acquire(False)
            if locked == True:
                try:
                    self._telemetry = self.command('getStatus')
                    logger.debug("[%s] - self._telemetry %s", self.__class__.__name__, self._telemetry)
                    self._status = self._telemetry['status']
                    self._telemetry['robot_status'] = json_loads(self._telemetry['robot_status'])
                    self._battery = self._telemetry['robot_status']['batPct']
                    self._battery_left = self._telemetry['robot_status']['expireM']
                    self._battery_charge = self._telemetry['robot_status']['rechrgM']
                    self._cycle = self._telemetry['robot_status']['cycle']
                    self._phase = self._telemetry['robot_status']['phase']
                    self._telemetry_last = True
                except Exception:
                    logger.exception("[%s] - Exception in get_telemetry", self.__class__.__name__)
                    self._telemetry_last = False
                finally:
                    self._lock.release()
                secs = self.values['ip_ping_poll'].data
                if secs < 0:
                    secs=60
                self._telemetry_next_run = datetime.now() + timedelta(seconds=secs)