Ejemplo n.º 1
0
    def discover_node(self, node, uid):
        """Discover resources available on a node."""
        coap_node_url = 'coap://[{}]'.format(node.address)
        if len(node.endpoints) == 0:
            logger.debug("Discovering CoAP node {}".format(node.address))
            code, payload = yield _coap_resource(
                '{0}/.well-known/core'.format(coap_node_url), method=GET)
            node.endpoints = _coap_endpoints(payload)

        endpoints = [
            endpoint for endpoint in node.endpoints
            if 'well-known/core' not in endpoint
        ]
        logger.debug("Fetching CoAP node resources: {}".format(endpoints))
        for endpoint in endpoints:
            elems = endpoint.split(';')
            path = elems.pop(0).replace('<', '').replace('>', '')

            try:
                code, payload = yield _coap_resource('{0}{1}'.format(
                    coap_node_url, path),
                                                     method=GET)
            except:
                logger.debug("Cannot discover ressource {} on node {}".format(
                    endpoint, node.address))
                return

            # Remove '/' from path
            path = path[1:]
            self._on_message_cb(Msg.update_node(uid, path, payload))
            self.nodes[node]['data'].update({path: payload})

        logger.debug(
            "CoAP node resources '{}' sent to broker".format(endpoints))
Ejemplo n.º 2
0
 def handle_coap_post(self, address, endpoint, value):
     """Handle CoAP post message sent from coap node."""
     node = CoapNode(address)
     if node in self.nodes and endpoint in self.nodes[node]['data']:
         self.nodes[node]['data'][endpoint] = value
     self._on_message_cb(
         Msg.update_node(self.nodes[node]['uid'], endpoint, value))
Ejemplo n.º 3
0
 def handle_node_check(self, data):
     """Handle alive message received from coap node."""
     node_id = data['id']
     node = MQTTNode(node_id)
     node.check_time = time.time()
     if node not in self.nodes:
         resources_topic = 'node/{}/resources'.format(node_id)
         yield from self.mqtt_client.subscribe([(resources_topic, QOS_1)])
         logger.debug("Subscribed to topic: {}".format(resources_topic))
         node_uid = str(uuid.uuid4())
         self.nodes.update(
             {node: {
                 'uid': node_uid,
                 'data': {
                     'protocol': PROTOCOL
                 }
             }})
         logger.debug("Available nodes: {}".format(self.nodes))
         self._on_message_cb(Msg.new_node(node_uid))
         self._on_message_cb(Msg.update_node(node_uid, "protocol",
                                             PROTOCOL))
         discover_topic = 'gateway/{}/discover'.format(node_id)
         yield from self.mqtt_client.publish(discover_topic,
                                             b"resources",
                                             qos=QOS_1)
         logger.debug("Published '{}' to topic: {}".format(
             "resources", discover_topic))
     else:
         data = self.nodes.pop(node)
         self.nodes.update({node: data})
     logger.debug("Available nodes: {}".format(self.nodes))
Ejemplo n.º 4
0
 def forward_data_from_node(self, node, resource, value):
     """Send data received from a node to the broker via the gateway."""
     logger.debug(
         "Sending data received from node '{}': '{}', '{}'.".format(
             node, resource, value))
     node.set_resource_value(resource, value)
     self.send_to_broker(Message.update_node(node.uid, resource, value))
Ejemplo n.º 5
0
    def send_data_to_node(self, data):
        """Forward received message data to the destination node.

        The message should be JSON and contain 'uid', 'path' and 'payload'
        keys.

        - 'uid' corresponds to the node uid (uuid)
        - 'path' corresponds to the CoAP resource on the node
        - 'payload' corresponds to the new payload for the CoAP resource.
        """
        uid = data['uid']
        endpoint = data['endpoint']
        payload = data['payload']
        logger.debug("Translating message ('{}') received to CoAP PUT "
                     "request".format(data))

        for node, _ in self.nodes.items():
            if self.nodes[node]['uid'] == uid:
                address = self.nodes[node]['data']['ip']
                logger.debug("Updating CoAP node '{}' resource '{}'".format(
                    self.nodes[node]['data']['ip'], endpoint))
                code, p = yield _coap_resource('coap://[{0}]/{1}'.format(
                    address, endpoint),
                                               method=PUT,
                                               payload=payload.encode('ascii'))
                if code == Code.CHANGED:
                    self.nodes[node]['data'][endpoint] = payload
                    yield self._on_message_cb(
                        Msg.update_node(uid, endpoint, payload))
                break
Ejemplo n.º 6
0
 def fetch_nodes_cache(self, source):
     """Send cached nodes information."""
     logger.debug("Fetching cached information of registered nodes.")
     for _, node in self.nodes.items():
         self._on_message_cb(Msg.new_node(node['uid'], dst=source))
         for endpoint, value in node['data'].items():
             yield self._on_message_cb(
                 Msg.update_node(node['uid'], endpoint, value, dst=source))
Ejemplo n.º 7
0
 def add_node(self, node):
     """Add a new node to the list of nodes and notify the broker."""
     node.set_resource_value('protocol', self.PROTOCOL)
     self.nodes.update({node.uid: node})
     self.send_to_broker(Message.new_node(node.uid))
     for res, value in node.resources.items():
         self.send_to_broker(Message.update_node(node.uid, res, value))
     yield self.discover_node(node)
Ejemplo n.º 8
0
 def fetch_nodes_cache(self, source):
     """Send cached nodes information."""
     logger.debug(
         "Fetching cached information of registered nodes '{}'.".format(
             self.nodes))
     for _, value in self.nodes.items():
         self._on_message_cb(Msg.new_node(value['uid'], dst=source))
         for resource, data in value['data'].items():
             self._on_message_cb(
                 Msg.update_node(value['uid'], resource, data, dst=source))
Ejemplo n.º 9
0
def test_update_node(value):
    serialized = Message.update_node('1234', 'test', 'value')

    assert serialized == Message.serialize({
        'type': 'update',
        'uid': '1234',
        'endpoint': 'test',
        'data': 'value',
        'dst': 'all'
    })

    serialized = Message.update_node('1234', 'test', value, '5678')
    assert serialized == Message.serialize({
        'type': 'update',
        'uid': '1234',
        'endpoint': 'test',
        'data': value,
        'dst': '5678'
    })
Ejemplo n.º 10
0
 def fetch_nodes_cache(self, source):
     """Send cached nodes information."""
     logger.debug("Fetching cached information of registered nodes.")
     for ws, node in self.nodes.items():
         self.send_to_broker(Message.new_node(node['uid'], dst=source))
         for endpoint, value in node['data'].items():
             self.send_to_broker(
                 Message.update_node(node['uid'],
                                     endpoint,
                                     value,
                                     dst=source))
Ejemplo n.º 11
0
 def handle_coap_alive(self, address):
     """Handle alive message received from coap node."""
     node = CoapNode(address)
     node.check_time = time.time()
     if node not in self.nodes:
         node_uid = str(uuid.uuid4())
         self.nodes.update({
             node: {
                 'uid': node_uid,
                 'data': {
                     'ip': address,
                     'protocol': 'coap'
                 }
             }
         })
         self._on_message_cb(Msg.new_node(node_uid))
         self._on_message_cb(Msg.update_node(node_uid, "ip", address))
         self._on_message_cb(Msg.update_node(node_uid, "protocol", 'coap'))
         self.discover_node(node, node_uid)
     else:
         data = self.nodes.pop(node)
         self.nodes.update({node: data})
Ejemplo n.º 12
0
    def fetch_nodes_cache(self, client):
        """Send cached nodes information to a given client.

        :param client: the ID of the client
        """
        logger.debug(
            "Fetching cached information of registered nodes '{}'.".format(
                self.nodes))
        for node in self.nodes.values():
            self.send_to_broker(Message.new_node(node.uid, dst=client))
            for resource, value in node.resources.items():
                self.send_to_broker(
                    Message.update_node(node.uid, resource, value, dst=client))
Ejemplo n.º 13
0
 def handle_coap_check(self, address, reset=False):
     """Handle check message received from coap node."""
     node = CoapNode(address)
     node.check_time = time.time()
     if node not in self.nodes:
         # This is a totally new node: create uid, initialized cached node
         # send 'new' node notification, 'update' notification.
         node_uid = str(uuid.uuid4())
         self.nodes.update({
             node: {
                 'uid': node_uid,
                 'data': {
                     'ip': address,
                     'protocol': PROTOCOL
                 }
             }
         })
         self._on_message_cb(Msg.new_node(node_uid))
         self._on_message_cb(Msg.update_node(node_uid, "ip", address))
         self._on_message_cb(Msg.update_node(node_uid, "protocol",
                                             PROTOCOL))
         self.discover_node(node, node_uid)
     elif reset:
         # The data of the node need to be reset without removing it. This
         # is particularly the case after a reboot of the node or a
         # firmware update of the node that triggered the reboot.
         node_uid = self.nodes[node]['uid']
         self.nodes[node]['data'] = {}
         self.nodes[node]['data'].update({
             'ip': address,
             'protocol': PROTOCOL
         })
         self._on_message_cb(Msg.reset_node(node_uid))
         self.discover_node(node, node_uid)
     else:
         # The node simply sent a check message to notify that it's still
         # online.
         data = self.nodes.pop(node)
         self.nodes.update({node: data})
Ejemplo n.º 14
0
 def on_node_message(self, ws, message):
     """Handle a message received from a node websocket."""
     if message['type'] == "update":
         logger.debug("New update message received from node websocket")
         for key, value in message['data'].items():
             if key in self.nodes[ws]['data']:
                 self.nodes[ws]['data'][key] = value
             else:
                 self.nodes[ws]['data'].update({key: value})
             self.send_to_broker(
                 Message.update_node(self.nodes[ws]['uid'], key, value))
     else:
         logger.debug("Invalid message received from node websocket")
Ejemplo n.º 15
0
    def handle_node_update(self, topic_name, data):
        """Handle CoAP post message sent from coap node."""
        _, node_id, resource = topic_name.split("/")
        node = MQTTNode(node_id)
        value = data['value']
        if node in self.nodes:
            if resource in self.nodes[node]['data']:
                # Add updated information to cache
                self.nodes[node]['data'][resource] = value
            else:
                self.nodes[node]['data'].update({resource: value})

        # Send update to broker
        self._on_message_cb(
            Msg.update_node(self.nodes[node]['uid'], resource, value))
Ejemplo n.º 16
0
 def open(self):
     """Discover nodes on each opened connection."""
     self.set_nodelay(True)
     logger.debug("New node websocket opened")
     self.application.nodes.update(
         {self: {
             'uid': str(uuid.uuid4()),
             'data': {
                 'protocol': PROTOCOL
             }
         }})
     node_uid = self.application.nodes[self]['uid']
     self.application.send_to_broker(Message.new_node(node_uid))
     yield self.write_message(Message.discover_node())
     self.application.send_to_broker(
         Message.update_node(node_uid, 'protocol', PROTOCOL))