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
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))
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")
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
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__)
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
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)
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)
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))
def on_message(self, client, userdata, message): """On generic message """ self.message = message self.payload=json_loads(message.payload)
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)