def read_property(self, td, name, timeout=None): """Reads the value of a Property on a remote Thing. Returns a Future.""" if name not in td.properties: raise FormNotFoundException() form = pick_form(td, td.get_property_forms(name), WebsocketSchemes.list()) if not form: raise FormNotFoundException() ws_url = form.resolve_uri(td.base) ref_id = uuid.uuid4().hex try: yield self._init_conn(ws_url, ref_id) msg_req = WebsocketMessageRequest( method=WebsocketMethods.READ_PROPERTY, params={"name": name}, msg_id=uuid.uuid4().hex) condition = yield self._send_message(ws_url, msg_req) timeout = datetime.timedelta(seconds=timeout) if timeout else None cond_res = yield condition.wait(timeout=timeout) if not cond_res: raise ClientRequestTimeout self._raise_message(ws_url, msg_req.id) finally: yield self._stop_conn(ws_url, ref_id)
def on_property_change(self, td, name): """Subscribes to property changes on a remote Thing. Returns an Observable.""" if name not in td.properties: # noinspection PyUnresolvedReferences return Observable.throw(FormNotFoundException()) form = pick_form(td, td.get_property_forms(name), WebsocketSchemes.list()) if not form: # noinspection PyUnresolvedReferences return Observable.throw(FormNotFoundException()) ws_url = form.resolve_uri(td.base) msg_req = WebsocketMessageRequest( method=WebsocketMethods.ON_PROPERTY_CHANGE, params={"name": name}, msg_id=uuid.uuid4().hex) def on_next(observer, msg_item): init_name = msg_item.data["name"] init_value = msg_item.data["value"] init = PropertyChangeEventInit(name=init_name, value=init_value) observer.on_next(PropertyChangeEmittedEvent(init=init)) subscribe = self._build_subscribe(ws_url, msg_req, on_next) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_event(self, td, name): """Subscribes to an event on a remote Thing. Returns an Observable.""" if name not in td.events: # noinspection PyUnresolvedReferences return Observable.throw(FormNotFoundException()) form = pick_form(td, td.get_event_forms(name), WebsocketSchemes.list()) if not form: # noinspection PyUnresolvedReferences return Observable.throw(FormNotFoundException()) ws_url = form.resolve_uri(td.base) msg_req = WebsocketMessageRequest(method=WebsocketMethods.ON_EVENT, params={"name": name}, msg_id=uuid.uuid4().hex) def on_next(observer, msg_item): observer.on_next(EmittedEvent(init=msg_item.data, name=name)) subscribe = self._build_subscribe(ws_url, msg_req, on_next) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_event(self, td, name, qos=QOS_0): """Subscribes to an event on a remote Thing. Returns an Observable.""" forms = td.get_event_forms(name) href = self._pick_mqtt_href(td, forms, op=InteractionVerbs.SUBSCRIBE_EVENT) if href is None: raise FormNotFoundException() parsed_href = self._parse_href(href) broker_url = parsed_href["broker_url"] topic = parsed_href["topic"] def next_item_builder(msg_data): return EmittedEvent(init=msg_data.get("data"), name=name) subscribe = self._build_subscribe(broker_url=broker_url, topic=topic, next_item_builder=next_item_builder, qos=qos) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_property_change(self, td, name, qos=QOS_0): """Subscribes to property changes on a remote Thing. Returns an Observable""" forms = td.get_property_forms(name) href = self._pick_mqtt_href(td, forms, op=InteractionVerbs.OBSERVE_PROPERTY) if href is None: raise FormNotFoundException() parsed_href = self._parse_href(href) broker_url = parsed_href["broker_url"] topic = parsed_href["topic"] def next_item_builder(msg_data): msg_value = msg_data.get("value") init = PropertyChangeEventInit(name=name, value=msg_value) return PropertyChangeEmittedEvent(init=init) subscribe = self._build_subscribe(broker_url=broker_url, topic=topic, next_item_builder=next_item_builder, qos=qos) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
async def read_property(self, td, name, timeout=None): """Reads the value of a Property on a remote Thing.""" href = self._pick_coap_href(td, td.get_property_forms(name), op=InteractionVerbs.READ_PROPERTY) if href is None: raise FormNotFoundException() coap_client = await aiocoap.Context.create_client_context() try: msg = aiocoap.Message(code=aiocoap.Code.GET, uri=href) request = coap_client.request(msg) try: response = await asyncio.wait_for(request.response, timeout=timeout) except asyncio.TimeoutError: raise ClientRequestTimeout self._assert_success(response) prop_value = json.loads(response.payload).get("value") return prop_value finally: await coap_client.shutdown()
def write_property(self, td, name, value, timeout=None): """Updates the value of a Property on a remote Thing. Returns a Future.""" con_timeout = timeout if timeout else self._connect_timeout req_timeout = timeout if timeout else self._request_timeout href = self.pick_http_href(td, td.get_property_forms(name)) if href is None: raise FormNotFoundException() http_client = tornado.httpclient.AsyncHTTPClient() body = json.dumps({"value": value}) try: http_request = tornado.httpclient.HTTPRequest( href, method="PUT", body=body, headers=self.JSON_HEADERS, connect_timeout=con_timeout, request_timeout=req_timeout) except HTTPTimeoutError: raise ClientRequestTimeout yield http_client.fetch(http_request)
def read_property(self, td, name, timeout=None): """Reads the value of a Property on a remote Thing. Returns a Future.""" con_timeout = timeout if timeout else self._connect_timeout req_timeout = timeout if timeout else self._request_timeout href = self.pick_http_href(td, td.get_property_forms(name)) if href is None: raise FormNotFoundException() http_client = tornado.httpclient.AsyncHTTPClient() try: http_request = tornado.httpclient.HTTPRequest( href, method="GET", connect_timeout=con_timeout, request_timeout=req_timeout) except HTTPTimeoutError: raise ClientRequestTimeout response = yield http_client.fetch(http_request) raise tornado.gen.Return(json.loads(response.body).get("value"))
async def write_property(self, td, name, value, timeout=None): """Updates the value of a Property on a remote Thing.""" href = self._pick_coap_href(td, td.get_property_forms(name), op=InteractionVerbs.WRITE_PROPERTY) if href is None: raise FormNotFoundException() coap_client = await aiocoap.Context.create_client_context() try: payload = json.dumps({"value": value}).encode("utf-8") msg = aiocoap.Message(code=aiocoap.Code.PUT, payload=payload, uri=href) request = coap_client.request(msg) try: response = await asyncio.wait_for(request.response, timeout=timeout) except asyncio.TimeoutError: raise ClientRequestTimeout self._assert_success(response) finally: await coap_client.shutdown()
def invoke_action(self, td, name, input_value, timeout=None): """Invokes an Action on a remote Thing. Returns a Future.""" if name not in td.actions: raise FormNotFoundException() form = pick_form(td, td.get_action_forms(name), WebsocketSchemes.list()) if not form: raise FormNotFoundException() ws_url = form.resolve_uri(td.base) ref_id = uuid.uuid4().hex try: yield self._init_conn(ws_url, ref_id) msg_req = WebsocketMessageRequest( method=WebsocketMethods.INVOKE_ACTION, params={ "name": name, "parameters": input_value }, msg_id=uuid.uuid4().hex) condition = yield self._send_message(ws_url, msg_req) timeout = datetime.timedelta(seconds=timeout) if timeout else None cond_res = yield condition.wait(timeout=timeout) if not cond_res: raise ClientRequestTimeout self._raise_message(ws_url, msg_req.id) finally: yield self._stop_conn(ws_url, ref_id)
async def invoke_action(self, td, name, input_value, timeout=None): """Invokes an Action on a remote Thing.""" href = self._pick_coap_href(td, td.get_action_forms(name), op=InteractionVerbs.INVOKE_ACTION) if href is None: raise FormNotFoundException() coap_client = await aiocoap.Context.create_client_context() try: invocation_id = await self._invocation_create(coap_client, href, input_value, timeout=timeout) request_obsv, response_obsv = await self._invocation_observe( coap_client, href, invocation_id, timeout=timeout) invocation_status = json.loads(response_obsv.payload) now = time.time() while not invocation_status.get("done"): if timeout and (time.time() - now) > timeout: raise ClientRequestTimeout response_obsv = await self._invocation_next(request_obsv, timeout=timeout) invocation_status = json.loads(response_obsv.payload) if not request_obsv.observation.cancelled: request_obsv.observation.cancel() if invocation_status.get("error"): raise Exception(invocation_status.get("error")) else: return invocation_status.get("result") finally: await coap_client.shutdown()
def on_property_change(self, td, name): """Subscribes to property changes on a remote Thing. Returns an Observable""" href = self._pick_coap_href(td, td.get_property_forms(name), op=InteractionVerbs.OBSERVE_PROPERTY) if href is None: raise FormNotFoundException() def next_item_builder(payload): value = json.loads(payload).get("value") init = PropertyChangeEventInit(name=name, value=value) return PropertyChangeEmittedEvent(init=init) subscribe = self._build_subscribe(href, next_item_builder) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_event(self, td, name): """Subscribes to an event on a remote Thing. Returns an Observable.""" href = self._pick_coap_href(td, td.get_event_forms(name), op=InteractionVerbs.SUBSCRIBE_EVENT) if href is None: raise FormNotFoundException() def next_item_builder(payload): if payload: data = json.loads(payload).get("data") return EmittedEvent(init=data, name=name) else: return None subscribe = self._build_subscribe(href, next_item_builder) # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_property_change(self, td, name): """Subscribes to property changes on a remote Thing. Returns an Observable""" href = self.pick_http_href(td, td.get_property_forms(name), op=InteractionVerbs.OBSERVE_PROPERTY) if href is None: raise FormNotFoundException() def subscribe(observer): """Subscription function to observe property updates using the HTTP protocol.""" state = {"active": True} @handle_observer_finalization(observer) @tornado.gen.coroutine def callback(): http_client = tornado.httpclient.AsyncHTTPClient() http_request = tornado.httpclient.HTTPRequest(href, method="GET") while state["active"]: try: response = yield http_client.fetch(http_request) value = json.loads(response.body).get("value") init = PropertyChangeEventInit(name=name, value=value) observer.on_next(PropertyChangeEmittedEvent(init=init)) except HTTPTimeoutError: pass def unsubscribe(): state["active"] = False tornado.ioloop.IOLoop.current().add_callback(callback) return unsubscribe # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def on_event(self, td, name): """Subscribes to an event on a remote Thing. Returns an Observable.""" href = self.pick_http_href(td, td.get_event_forms(name)) if href is None: raise FormNotFoundException() def subscribe(observer): """Subscription function to observe events using the HTTP protocol.""" state = {"active": True} @handle_observer_finalization(observer) @tornado.gen.coroutine def callback(): http_client = tornado.httpclient.AsyncHTTPClient() http_request = tornado.httpclient.HTTPRequest(href, method="GET") while state["active"]: try: response = yield http_client.fetch(http_request) payload = json.loads(response.body).get("payload") observer.on_next(EmittedEvent(init=payload, name=name)) except HTTPTimeoutError: pass def unsubscribe(): state["active"] = False tornado.ioloop.IOLoop.current().add_callback(callback) return unsubscribe # noinspection PyUnresolvedReferences return Observable.create(subscribe)
def invoke_action(self, td, name, input_value, timeout=None): """Invokes an Action on a remote Thing. Returns a Future.""" con_timeout = timeout if timeout else self._connect_timeout req_timeout = timeout if timeout else self._request_timeout now = time.time() href = self.pick_http_href(td, td.get_action_forms(name)) if href is None: raise FormNotFoundException() body = json.dumps({"input": input_value}) http_client = tornado.httpclient.AsyncHTTPClient() try: http_request = tornado.httpclient.HTTPRequest( href, method="POST", body=body, headers=self.JSON_HEADERS, connect_timeout=con_timeout, request_timeout=req_timeout) except HTTPTimeoutError: raise ClientRequestTimeout response = yield http_client.fetch(http_request) invocation_url = json.loads(response.body).get("invocation") @tornado.gen.coroutine def check_invocation(): parsed = parse.urlparse(href) invoc_href = "{}://{}/{}".format( parsed.scheme, parsed.netloc, invocation_url.lstrip("/")) invoc_http_req = tornado.httpclient.HTTPRequest( invoc_href, method="GET", connect_timeout=con_timeout, request_timeout=req_timeout) self._logr.debug("Checking invocation: {}".format(invocation_url)) try: invoc_res = yield http_client.fetch(invoc_http_req) except HTTPTimeoutError: self._logr.debug("Timeout checking invocation: {}".format(invocation_url)) raise tornado.gen.Return((False, None)) status = json.loads(invoc_res.body) if status.get("done") is False: raise tornado.gen.Return((False, None)) if status.get("error") is not None: raise tornado.gen.Return((True, Exception(status.get("error")))) else: raise tornado.gen.Return((True, tornado.gen.Return(status.get("result")))) while True: done, result = yield check_invocation() if done: raise result elif timeout and (time.time() - now) > timeout: raise ClientRequestTimeout
def invoke_action(self, td, name, input_value, timeout=None, qos_publish=QOS_2, qos_subscribe=QOS_1): """Invokes an Action on a remote Thing. Returns a Future.""" timeout = timeout if timeout else self._timeout_default ref_id = uuid.uuid4().hex href = self._pick_mqtt_href(td, td.get_action_forms(name)) if href is None: raise FormNotFoundException() parsed_href = self._parse_href(href) broker_url = parsed_href["broker_url"] topic_invoke = parsed_href["topic"] topic_result = ActionMQTTHandler.to_result_topic(topic_invoke) try: yield self._init_client(broker_url, ref_id) yield self._subscribe(broker_url, topic_result, qos_subscribe) input_data = {"id": uuid.uuid4().hex, "input": input_value} input_payload = json.dumps(input_data).encode() yield self._publish(broker_url, topic_invoke, input_payload, qos_publish) ini = time.time() while True: self._logr.debug( "Checking invocation topic: {}".format(topic_result)) if timeout and (time.time() - ini) > timeout: self._logr.warning( "Timeout invoking Action: {}".format(topic_result)) raise ClientRequestTimeout msg_match = self._next_match( broker_url, topic_result, lambda item: item[1].get("id") == input_data.get("id")) if not msg_match: yield self._wait_on_message(broker_url, topic_result) continue msg_id, msg_data, msg_time = msg_match if msg_data.get("error", None) is not None: raise Exception(msg_data.get("error")) else: raise tornado.gen.Return(msg_data.get("result")) finally: yield self._disconnect_client(broker_url, ref_id)
def write_property(self, td, name, value, timeout=None, qos_publish=QOS_2, qos_subscribe=QOS_1, wait_ack=True): """Updates the value of a Property on a remote Thing. Due to the MQTT binding design this coroutine yields as soon as the write message has been published and will not wait for a custom write handler that yields to another coroutine Returns a Future.""" timeout = timeout if timeout else self._timeout_default ref_id = uuid.uuid4().hex href_write = self._pick_mqtt_href(td, td.get_property_forms(name), op=InteractionVerbs.WRITE_PROPERTY) if href_write is None: raise FormNotFoundException() parsed_href_write = self._parse_href(href_write) broker_url = parsed_href_write["broker_url"] topic_write = parsed_href_write["topic"] topic_ack = PropertyMQTTHandler.to_write_ack_topic(topic_write) try: yield self._init_client(broker_url, ref_id) yield self._subscribe(broker_url, topic_ack, qos_subscribe) write_data = { "action": "write", "value": value, "ack": uuid.uuid4().hex } write_payload = json.dumps(write_data).encode() yield self._publish(broker_url, topic_write, write_payload, qos_publish) if not wait_ack: return ini = time.time() while True: self._logr.debug( "Checking write ACK topic: {}".format(topic_ack)) if timeout and (time.time() - ini) > timeout: self._logr.warning( "Timeout writing Property: {}".format(topic_ack)) raise ClientRequestTimeout msg_match = self._next_match( broker_url, topic_ack, lambda item: item[1].get("ack") == write_data.get("ack")) if msg_match: break yield self._wait_on_message(broker_url, topic_ack) finally: yield self._disconnect_client(broker_url, ref_id)
def read_property(self, td, name, timeout=None, qos_publish=QOS_1, qos_subscribe=QOS_1): """Reads the value of a Property on a remote Thing. Returns a Future.""" timeout = timeout if timeout else self._timeout_default ref_id = uuid.uuid4().hex forms = td.get_property_forms(name) href_read = self._pick_mqtt_href(td, forms, op=InteractionVerbs.READ_PROPERTY) href_obsv = self._pick_mqtt_href(td, forms, op=InteractionVerbs.OBSERVE_PROPERTY) if href_read is None or href_obsv is None: raise FormNotFoundException() parsed_href_read = self._parse_href(href_read) parsed_href_obsv = self._parse_href(href_obsv) topic_read = parsed_href_read["topic"] topic_obsv = parsed_href_obsv["topic"] broker_read = parsed_href_read["broker_url"] broker_obsv = parsed_href_obsv["broker_url"] try: yield self._init_client(broker_read, ref_id) broker_obsv != broker_read and (yield self._init_client( broker_obsv, ref_id)) yield self._subscribe(broker_obsv, topic_obsv, qos_subscribe) read_time = time.time() read_payload = json.dumps({"action": "read"}).encode() yield self._publish(broker_read, topic_read, read_payload, qos_publish) ini = time.time() while True: self._logr.debug( "Checking property update topic: {}".format(topic_obsv)) if timeout and (time.time() - ini) > timeout: self._logr.warning( "Timeout reading Property: {}".format(topic_obsv)) raise ClientRequestTimeout msg_match = self._next_match(broker_obsv, topic_obsv, lambda item: item[2] >= read_time) if not msg_match: yield self._wait_on_message(broker_obsv, topic_obsv) continue msg_id, msg_data, msg_time = msg_match raise tornado.gen.Return(msg_data.get("value")) finally: yield self._disconnect_client(broker_read, ref_id) broker_obsv != broker_read and (yield self._disconnect_client( broker_obsv, ref_id))