def render_DELETE(self, request): logger.info("RD: DELETE to /rd from {host}:{port}".format( host=request.source[0], port=request.source[1])) DB.DB.remove_endpoint() device = device_translator.convert_to_device_instance(informations) Client.delete(device) return True
def execute_task(self, task): coap_client = HelperClient("127.0.0.1", 5683) response = coap_client.get("/rd-lookup/ep?id={id}".format(id=task)) links = core_link_format_helper.parse_links(response) device = links[0] uri = request_helper.parse_url(device.get("path")) coap_client = HelperClient((uri.hostname, uri.port)) try: logger.info( "EXECUTER: Send command to {host}:{port} with id: {id}".format( host=uri.hostname, port=uri.port, id=id)) config = task.get("metadata") service = task.get("data") if config == "GET": coap_client.get(device.get("path") + service) elif config == "POST": coap_client.post(device.get("path") + service, task) elif config == "PUT": coap_client.put(device.get("path") + service, task) elif config == "DELETE": coap_client.delete(device.get("path") + service) logger.info("EXECUTER: Send command was sucsessful") except Exception as e: logger.error("EXECUTER: Send command was not successful") try: logger.info("EXECUTER: Send response to platform") Client.response(task, task) except Exception as e: logger.error( "OBSERVER: Send response to platform was not successful")
def __on_message(self, client, userdata, message): try: message = json.loads(message.payload.decode()) if message['msg'] == 'ENVIRONMENTAL-CURRENT-SENSOR-DATA': for reading in self.device.parseEnvironmentSensors(message): Client.event( self.device, reading[0], json.dumps({ 'value': reading[1], 'unit': reading[2], 'time': reading[3] }), block=False ) time.sleep(0.1) elif message['msg'] == 'CURRENT-STATE': self.device.state = message.get('product-state') if not self.init_state.is_set(): self.init_state.set() elif message['msg'] == 'STATE-CHANGE': self.device.updateState(message.get('product-state')) else: logger.warning("unknown message: '{}'".format(message)) except Exception as ex: logger.error("malformed message: '{}'".format(ex))
def add_device(self,device): """ Add a new device, regardless of its connection status """ # TODO set status to connected/disconnected on device creation Yann? status = device.get("statusInfo") if status: if status.get("status") == "ONLINE": logger.info("'{}' is online trying to add ...".format(device.get("label"))) device_type_json_formatted = self.get_device_type_json(device) found_on_platform, device_type_patform_id = self.get_platform_id(device_type_json_formatted) logger.info("device type " + json.loads(device_type_json_formatted).get("name") + " found on platform? " + str(found_on_platform)) # if platform id exists then the device type was created already if found_on_platform: logger.info("found device type: " + str(device_type_patform_id)) else: # device_type_patform_id = self.create_type_on_platform(device_type_json_formatted) logger.info("generated device type: " + str(device_type_patform_id)) if device_type_patform_id: formatted_device = self.format(device, device_type_patform_id) Client.add(formatted_device) logger.info("added new device") else: logger.info("'{}' is offline - no further action".format(device.get("label")))
def render_POST(self, request): logger.info("RD: POST to /rd from {host}:{port}".format( host=request.source[0], port=request.source[1])) print(request.pretty_print()) logger.info("RD: Payload: {payload}".format(payload=request.payload)) res = RDResource() if request.payload: informations = { "host": request.source[0], "port": request.source[1], "query_parameters": request_helper.get_query_parameter(request), "links": core_link_format_helper.parse_links(request.payload), } ep = informations.get("query_parameters").get("ep") if not DB.DB.endpoint_exists(ep): # todo check ip change DB.DB.create(informations) logger.info( 'RD: Endpoint not found -> created in local db and register on platform' ) id = DB.DB.get_endpoint_id(ep) device = DB.DB.get(id) res.location_path = "/rd/{id}".format( id=id) # todo nicht da in respone Client.add(device) else: logger.info("RD: Endpoint exists -> return found id") # todo reconnect by Client.add() ? res.location_path = "/rd/" + str(DB.DB.get_endpoint_id(ep)) return res
def ping(self, device_id): response = self.openhab_api_manager.get_thing(device_id) status = response.get("statusInfo") if status: if status.get("status") == "OFFLINE": Client.disconnect(device_id) elif status == "ONLINE": device = device_pool.DevicePool.get(device_id) Client.add(device)
def __on_connect(self, client, userdata, flags, rc): if rc == 0: logger.info("connected to broker '{}' on '{}'".format(self.ip_address, self.port)) self.mqtt_c.subscribe("{0}/{1}/status/current".format(self.device.product_type, self.device.id)) try: Client.add(self.device) except AttributeError: DevicePool.add(self.device) self.__requestDeviceStates() self.device_sensor_request.start() else: logger.error("could not connect to broker '{}' on '{}' - reason '{}'".format(self.ip_address, self.port, rc))
def run(self): logger.info("starting executor ...") while True: message = Client.receive() logger.debug(message) response = self.get_command(message) Client.response(message, response, metadata=None, timeout=10, callback=None, block=True)
def getReading(source): payload = dict() while True: readings = source.read() if readings: payload['value'] = float(readings['1.8.0'][0]) payload['unit'] = readings['1.8.0'][1] payload['time'] = '{}Z'.format( datetime.datetime.utcnow().isoformat()) Client.event(device=SM_ID, service=SEPL_SERVICE, data=json.dumps(payload))
def _evaluate(self, unknown_devices): missing_devices, new_devices = self._diff(device_pool.DevicePool.devices(), unknown_devices) if missing_devices: logger.info(str(len(new_devices)) + " devices were deleted on OpenHAB") for device in missing_devices: Client.delete(device) if new_devices: for device in new_devices: try: logger.info("Found device: '{}'".format(device.get("label"))) self.add_device(device) except Exception as e: logger.error(e)
def router(): while True: task = Client.receive() try: for part in task.payload.get('protocol_parts'): if part.get('name') == 'data': command = json.loads(part.get('value')) session = SessionManager.sessions.get(task.payload.get('device_url')) session.command_queue.put(command) Client.response(task, '200') except Exception as ex: Client.response(task, '500') logger.error("could not route command '{}' for '{}'".format(task.payload.get('protocol_parts'), task.payload.get('device_url'))) logger.error(ex)
def render_POST(self, request): res = UpdateResource() print("POST to /rd/[id] from {host}:{port}".format( host=request.source[0], port=request.source[1])) informations = { 'query_parameters': request_helper.get_query_parameter(request), 'links': core_link_format_helper.parse_links( request.payload.decode('utf-8')), } id = request.uri_path.split("/")[-1] device = self.db.get(id) Client.update(device) return res
def setSettings(self, rpkwh, kwh, name): if type(kwh) is str: kwh = kwh.replace(',', '.') if devices_db.updateDevice(self._id, rpkwh=int(rpkwh), kwh=float(kwh), name=str(name)): self._rpkwh = int(rpkwh) self._kwh = float(kwh) self._meter_name = str(name) if not self._device.name == self._meter_name: self._device.name = self._meter_name try: Client.update(self._device) except AttributeError: DevicePool.update(self._device)
def handle_mutlicast_responses(self, response): print(response.pretty_print()) if not DB.DB.host_exists(response.source[0]): # todo check ip change informations = { "host": response.source[0], "port": response.source[1], "query_parameters": { "ep": "Unknown Name" }, "links": core_link_format_helper.parse_links(response.payload), } id = DB.DB.create(informations) device = DB.DB.get(id) Client.add(device)
def pushReadings(): while True: for controller in SerialManager.getControllers(): try: Client.event( controller._extended_id, 'detection', json.dumps({ 'value': float(controller._kwh), 'unit': 'kWh', 'time': '{}Z'.format(datetime.datetime.utcnow().isoformat()) }), block=False ) time.sleep(0.1) except Exception as ex: logger.error(ex) time.sleep(20)
def _evaluate(self, unknown_devices, init): missing_devices, new_devices, changed_devices = self._diff(__class__._known_devices, unknown_devices) if missing_devices: for missing_device_id in missing_devices: logger.info("can't find '{}' with id '{}'".format(__class__._known_devices[missing_device_id].get('name'), missing_device_id)) del __class__.bridge_map[missing_device_id] if init: DevicePool.remove(missing_device_id) else: Client.disconnect(missing_device_id) if new_devices: for new_device_id in new_devices: name = unknown_devices[new_device_id].get('name') logger.info("found '{}' with id '{}'".format(name, new_device_id)) __class__.bridge_map[new_device_id] = (unknown_devices[new_device_id].get('LIGHT_KEY'), Converter(get_light_gamut(unknown_devices[new_device_id].get('modelid')))) device = Device(new_device_id, SEPL_DEVICE_TYPE, name) device.addTag('type', unknown_devices[new_device_id].get('type')) device.addTag('manufacturer', unknown_devices[new_device_id].get('manufacturername')) if init: DevicePool.add(device) else: Client.add(device) if changed_devices: for changed_device_id in changed_devices: device = DevicePool.get(changed_device_id) name = unknown_devices[changed_device_id].get('name') if not name == device.name: device.name = name if init: DevicePool.update(device) else: Client.update(device) logger.info("name of '{}' changed to {}".format(changed_device_id, name)) __class__._known_devices = unknown_devices
def run(self): logger.debug("starting serial controller for device '{}'".format( self._id)) self._writeSerialLog('serial connection open') self._writeSerialLog(self._greeting, 'D') if self._waitFor('RDY'): self._writeSerialLog('RDY', 'D') logger.info("started serial controller for device '{}'".format( self._id)) logger.debug(self._serial_con) if self._configureDevice(init=True): try: Client.add(self._device) except AttributeError: DevicePool.add(self._device) if self._strt: self.startDetection() while True: try: command, callbk, kwargs = self._commands.get(timeout=1) if command != self._stopAction: if kwargs: command(callbk, **kwargs) else: command(callbk) else: callbk(409) except Empty: pass except __class__.Interrupt: break try: Client.disconnect(self._device) except AttributeError: DevicePool.remove(self._device) else: logger.error("device '{}' not ready".format(self._id)) self._closeConnection() logger.info("serial controller for device '{}' exited".format( self._id))
def run(self): # Get data via CoAP Observe request # self.check_observations() # Get data via frequently GET requests (maybe as fallback if observe is not supported) while True: time.sleep(30) localhost_client = HelperClient(("127.0.0.1", 5683)) # Observe all sensor resources # todo id und status von endpoint bei join mitnehmen services_of_connected_devices = localhost_client.get( "lookup/res?status=1&if=core.s") for device in services_of_connected_devices: id = device.get("id") url = request_helper.parse_url(device.get("path")) logger.info( "OBSERVER: Perform GET to: {host}:{port} with id: {id}". format(host=url.hostname, port=url.port, id=id)) device_client = HelperClient((url.hostname, url.port)) response = None try: response = device_client.get(url.path) device = DB.DB.get(id) except Exception as e: logger.error("OBSERVER: GET was not successful") if response: try: # Data Type of platoform contain data and metadata # structure of data has to be defined in the service output parameter Client.event(device, service=url.path, data=json.dumps(response.payload)) except Exception as e: logger.error( "OBSERVER: Send data to platform was not successful" )
def run(self): logger.info("starting session for '{}'".format(self.device.id)) try: self.mqtt_c.connect(self.ip_address, self.port, keepalive=5) self.mqtt_c.loop_start() self.init_state.wait(timeout=10) if self.device.state: while not self.stop: try: command = self.command_queue.get(timeout=0.5) state = self.device.state for key, value in command.items(): if key in DysonDevice.state_map and value in DysonDevice.state_map[key]: state[key] = value payload = { "msg": "STATE-SET", "time": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()), "mode-reason": "LAPP", "data": state } self.mqtt_c.publish('{}/{}/command'.format(self.device.product_type, self.device.id), json.dumps(payload), 1) except Empty: pass except Exception as ex: logger.error("error handling command - '{}'".format(ex)) try: Client.disconnect(self.device) except AttributeError: DevicePool.remove(self.device) else: self.mqtt_c.disconnect() logger.error("could not get device state for '{}'".format(self.device.id)) except TimeoutError as ex: logger.error("could not connect to broker '{}' on '{}' - reason '{}'".format(self.ip_address, self.port, ex)) self.mqtt_c.loop_stop() if self.device_sensor_request.is_alive(): self.device_sensor_request.join() SessionManager.cleanSession(self.device.id)
def _evaluate(self, unknown_devices): missing_devices, new_devices = self._diff(self._know_devices, unknown_devices) if missing_devices: for missing_device_id in missing_devices: logger.info("can't find '{}'".format(missing_device_id)) try: Client.delete(missing_device_id) except AttributeError: DevicePool.remove(missing_device_id) SessionManager.delRemoteDevice(missing_device_id) if new_devices: for new_device_id in new_devices: try: dyson_data = dyson_map[unknown_devices[new_device_id] ['ProductType']] dyson_device = DysonDevice( new_device_id, dyson_data['type'], dyson_data['name'], decrypt_password(unknown_devices[new_device_id] ['LocalCredentials']), unknown_devices[new_device_id]['ProductType'], unknown_devices[new_device_id]['ScaleUnit']) dyson_device.addTag('manufacturer', 'Dyson') count = '' for tag in dyson_data['tags']: dyson_device.addTag('type{}'.format(count), tag) if not count: count = 0 count = count + 1 logger.info("found '{}' with id '{}'".format( dyson_device.name, dyson_device.id)) SessionManager.addRemoteDevice(dyson_device) except KeyError: logger.error( "missing device data or malformed message - '{}'". format(unknown_devices[new_device_id])) self._know_devices = unknown_devices.keys()
def pushReadings(): while True: for device in DevicePool.devices().values(): try: response = http.get('http://{}/api/air/kick'.format(device.ip)) if response.status == 204: time.sleep(5) response = http.get('http://{}/api/air/state'.format(device.ip)) if response.status == 200: air_state = json.loads(response.body) for sensor in air_state['air']['sensors']: Client.event( device.id, 'reading_{}'.format(sensor['type']), json.dumps({ 'value': sensor['value'], 'unit': 'µg/m³', 'time': '{}Z'.format(datetime.datetime.utcnow().isoformat()) }), block=False ) except Exception as ex: logger.error(ex) time.sleep(20)
def router(): while True: task = Client.receive() try: for part in task.payload.get('protocol_parts'): if part.get('name') == 'data': command = part.get('value') http_resp = http.put( '{}/lights/id:{}/state'.format( LIFX_CLOUD_URL, task.payload.get('device_url') ), command, headers={ 'Authorization': 'Bearer {}'.format(LIFX_API_KEY), 'Content-Type': 'application/json' } ) if http_resp.status not in (200, 207): logger.error("could not route message to LIFX API - '{}'".format(http_resp.status)) response = str(http_resp.status) except Exception as ex: logger.error("error handling task - '{}'".format(ex)) response = '500' Client.response(task, response)
def _evaluate(self, unknown_devices): missing_devices, new_devices, changed_devices = self._diff(__class__._known_devices, unknown_devices) if missing_devices: for missing_device_id in missing_devices: logger.info("can't find '{}' with id '{}'".format(__class__._known_devices[missing_device_id].get('label'), missing_device_id)) try: Client.delete(missing_device_id) except AttributeError: DevicePool.remove(missing_device_id) if new_devices: for new_device_id in new_devices: name = unknown_devices[new_device_id].get('label') logger.info("found '{}' with id '{}'".format(name, new_device_id)) device = Device(new_device_id, SEPL_DEVICE_TYPE, name) product = unknown_devices[new_device_id].get('product') device.addTag('type', 'Extended color light') device.addTag('product', product.get('name')) device.addTag('manufacturer', product.get('company')) try: Client.add(device) except AttributeError: DevicePool.add(device) if changed_devices: for changed_device_id in changed_devices: seconds_since_seen = unknown_devices[changed_device_id].get('seconds_since_seen') if seconds_since_seen >= 60: try: Client.disconnect(changed_device_id) except AttributeError: DevicePool.remove(changed_device_id) del unknown_devices[changed_device_id] else: device = DevicePool.get(changed_device_id) name = unknown_devices[changed_device_id].get('label') if not name == device.name: device.name = name try: Client.update(device) except AttributeError: DevicePool.update(device) logger.info("name of '{}' changed to {}".format(changed_device_id, name)) __class__._known_devices = unknown_devices
def run(self): logger.info("Start observing of values") while True: time.sleep(int(config["CONNECTOR"]["ping_interval"])) logger.debug("get values from devices and push to platform") connected_devices = device_pool.DevicePool.devices() for device in connected_devices: device_json = self.openhab_api_manager.get_thing(device) channels = device_json.get("channels") for channel in channels: items = channel.get("linkedItems") if items: if len(items) != 0: try: service_response = self.openhab_api_manager.getItemState( items[0]) # convert depending on data type if channel.get("itemType") == "Number": service_response = float(service_response) payload = { "value": service_response, "time": datetime.datetime.utcnow().isoformat() } # channel type uid == service id logger.debug( "try to publish data from service: " + channel.get("channelTypeUID")) logger.debug("publish data: " + json.dumps(payload)) response = Client.event( device, channel.get("channelTypeUID"), json.dumps(payload)) logger.debug(response.status) except Exception as ex: logger.error("'{}': {}".format(items[0], ex))
def _evaluate(self, unknown_devices, init): missing_devices, new_devices, changed_devices = self._diff( __class__._known_devices, unknown_devices) if missing_devices: for missing_device_id in missing_devices: logger.info("can't find '{}' with id '{}'".format( __class__._known_devices[missing_device_id].get( 'deviceName'), missing_device_id)) if init: DevicePool.remove(missing_device_id) else: Client.disconnect(missing_device_id) if new_devices: for new_device_id in new_devices: name = unknown_devices[new_device_id].get('deviceName') logger.info("found '{}' with id '{}'".format( name, new_device_id)) device = BleboxDevice(new_device_id, SEPL_DEVICE_TYPE, name, unknown_devices[new_device_id].get('ip')) device.addTag('type', unknown_devices[new_device_id].get('type')) if init: DevicePool.add(device) else: Client.add(device) if changed_devices: for changed_device_id in changed_devices: device = DevicePool.get(changed_device_id) name = unknown_devices[changed_device_id].get('deviceName') if not name == device.name: device.name = name if init: DevicePool.update(device) else: Client.update(device) logger.info("name of '{}' changed to {}".format( changed_device_id, name)) __class__._known_devices = unknown_devices
def run(self): while True: #todo die disconnected auf connected umstellen wenn wieder da, # allles auf connected stellen wenn nicht eh schon auf connected time.sleep(10) local_coap_client = HelperClient(server=("127.0.0.1", 5683)) response = local_coap_client.get("/rd-lookup/ep") if response.payload: known_devices = core_link_format_helper.parse_links( response.payload) # ping unicast instead of multicast, dont know if the device listens on multicast missing_devices = [] reconnected_devices = [] for device in known_devices: url = request_helper.parse_url(device.get("path")) device_was_connected = None print(device) if device.get("status") == '1': device_was_connected = True elif device.get("status") == '0': device_was_connected = False is_online = self.ping(url.hostname, url.port) if not is_online and device_was_connected: missing_devices.append(device) if is_online and not device_was_connected: reconnected_devices.append(device) for device in missing_devices: id = device.get("id") logger.info( "PINGER: device {id} is not online -> disconnect". format(id=id)) device = DB.DB.get(id) try: Client.disconnect(device) logger.info( "PINGER: device {id} was disconnected from RD and platform" .format(id=id)) except Exception as e: logger.error( "PINGER: device {id} was not successful disconnected" .format(id=id)) logger.error(e) for device in reconnected_devices: id = device.get("id") logger.info( "PINGER: device {id} is online -> reconnect".format( id=id)) device = DB.DB.get(id) try: # For reconnect, use add() - maybe connect() better ? Client.add(device) logger.info( "PINGER: device {id} was added to platform".format( id=id)) except Exception as e: logger.error( "PINGER: device {id} was not successful added to platform" .format(id=id))
def handle_observe_response(self, response, id=None): if id and response: device = DB.DB.get(id) service = "" payload = response Client.event(device, service, payload)
if 0 in tests: logger.info('------ populate device manager ------') device_manager.add( Device(id_1, 'iot#d66ec9bc-e37f-4f35-a788-027301aad6c2', 'Dummy Device 1')) device_2 = Device(id_2, 'iot#d66ec9bc-e37f-4f35-a788-027301aad6c2', 'Dummy Device 2') device_2.addTag('type', 'Dummy') device_manager.add(device_2) device_manager.add( Device(id_3, 'iot#d66ec9bc-e37f-4f35-a788-027301aad6c2', 'Dummy Device 3')) if __name__ == '__main__': connector_client = Client(device_manager) logger.info('###### runtime phase ######') if 1 in tests: time.sleep(0.5) logger.info('------ add tag to existing device ------') device = device_manager.get(id_1) device.addTag('type', 'Dummy') Client.update(device) if 2 in tests: time.sleep(0.5) logger.info('------ change tag on existing device ------') device = device_manager.get(id_1) device.changeTag('type', 'dummy device')
logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')) logger.addHandler(fn) from coap_server import server from pinger import pinger from coap_executer import executer #from discovery import mdns_discovery #from discovery import coap_discovery if __name__ == '__main__': # initiation phase nicht notwenidg, da alles was connected ist, schon mit connected status in db sthet # hochstens bei start das nochmal uberprufen, aber passiet eh weiter unten # devices method liefert eh nur connected devices # nochmal chekcen vorher ?! synchron aber damit erst danach client connecion aufbaut # Start Web Socket connection and synchronize connected devices connector_client = Client(DB.DB()) # CoAP server listens on multicast and gets registration requests from devices # CoAP Server with registration und discovery endpoints coap_server = server.CoAPMulticastServer("0.0.0.0", 5683) coap_server.start() # CoAP Client for pining devices to update device manager coap_pinger = pinger.Pinger() coap_pinger.start() # Executer - Receive command and respond coap_executer = executer.Executer() coap_executer.start() # Observer - Gets data from connected devices and pushes them to the platform
for device in DevicePool.devices().values(): try: response = http.get('http://{}/api/air/kick'.format(device.ip)) if response.status == 204: time.sleep(5) response = http.get('http://{}/api/air/state'.format(device.ip)) if response.status == 200: air_state = json.loads(response.body) for sensor in air_state['air']['sensors']: Client.event( device.id, 'reading_{}'.format(sensor['type']), json.dumps({ 'value': sensor['value'], 'unit': 'µg/m³', 'time': '{}Z'.format(datetime.datetime.utcnow().isoformat()) }), block=False ) except Exception as ex: logger.error(ex) time.sleep(20) readings_scraper = Thread(target=pushReadings, name="Scraper") if __name__ == '__main__': device_monitor = Monitor() connector_client = Client(device_manager=DevicePool) readings_scraper.start()