def read_resource(self, server_ip, server_port, endpoint_name, object_id, res_id, object_inst_id=None, \
                   res_inst_id=None, client_port=5683):
     
     query = "?method=read"
     server_ip_port = server_ip + ":" + str(server_port)
     
     path = "rd/" + endpoint_name + "/" + str(object_id)
     if object_inst_id is not None:
         path += "/" + str(object_inst_id)
     else:
         path +="/0"
     if res_id is not None:
         path += "/" + str(res_id)
         if res_inst_id is not None:
             path += "/" +str(res_inst_id)
         else:
             path += "/0"
             
     payload = None
     #content_type = "application/json"
     path += query
     
     client = CoapClient("coap://" + server_ip_port, client_port=client_port)
     #result = client.get(path, data=payload, content_type=content_type)
     result = client.get(path, data=payload, timeout=10000)
     
     return result
 def send_observe_request(self, server_ip, server_port, app_ip, app_port, endpoint_name, object_id, observe, \
                            payload=None, object_inst_id=None, res_id=None, \
                            res_inst_id=None, content_type=None, token=None, client_port=5683):
     
     server_ip_port = server_ip + ":" + str(server_port)
     path = "rd"
     if payload is not None and endpoint_name is None:
         pass
     elif endpoint_name is not None:
         path += "/" + endpoint_name
         payload = dumps({"app_ip" : app_ip, "app_port" : app_port})
         content_type = "application/json"
         if object_id is not None:
             path += "/" + str(object_id)
             if object_inst_id is not None:
                 path += "/" + str(object_inst_id)
                 if res_id is not None:
                     path += "/" + str(res_id)
                     if res_inst_id is not None:
                         path += "/" + str(res_inst_id)
         else:
             message = "Object ID is missing"
             self.logger.error(message)
             return message
     else:
         message = "Endpoint is missing"
         self.logger.error(message)
         return message
     
     try:
         client = CoapClient("coap://" + server_ip_port, client_port=client_port)
         result = client.get(path, data=payload, observe=observe, content_type=content_type, token=token)
     except:
         return None
     return result
    def discover_resources(self, server_ip, server_port, payload=None, endpoint_name=None,
                                  object_id=None, object_inst_id=None, res_id=None, res_inst_id=None, client_port=5683):

        server_ip_port = server_ip + ":" + str(server_port)
        query = "?method=discover"
        content_type = None
        path = "rd"
        if payload is not None:
            """ ".well-known/core" is a payload """
            content_type = "text/plain"
        else:
            if (endpoint_name or object_id) is not None:
                path += "/" + endpoint_name + "/" + str(object_id)
                if object_inst_id is None and res_id is not None:
                    object_inst_id = 0
                    path += "/" + str(object_inst_id)
                elif object_inst_id is not None:
                    path += "/" + str(object_inst_id)
                
                if res_id is not None:
                    path += "/" + str(res_id)
                    if res_inst_id is None:
                        res_inst_id = 0
                    path += "/" + str(res_inst_id)
            else:
                self.logger.error("Endpoint Name and object_id should be specified")
                return
        path += query

        client = CoapClient("coap://" + server_ip_port, client_port=client_port)
        result = client.get(path, data=payload, timeout=10000, content_type=content_type)
        
        return result
class XIXCoap(LoggerMixin):
    def __init__(self, uri, client_port=None, *args, **kw):
        self.client = CoapClient(uri, client_port)
        self.logger.debug("CoapClient created with uri %s", uri)
        self.__serializer = JsonSerializer()
        self.methodmappers = {
            "create": self._send_create,
            "notify": self._send_notify,
            "update": self._send_update,
            "delete": self._send_delete,
            "retrieve": self._send_retrieve
        }

    def send_request_indication(self, request_indication):
        path = request_indication.path
        if path.startswith('/'):
            path = path[1:]

        mapper = self.methodmappers[request_indication.method]
        return mapper(request_indication, path)

    def _raise_error(self, method, response):
        try:
            status_code = _coap2etsi[response.code]
        except KeyError:
            self.logger.warning("Failed to map coap response code: %s",
                                response.code)
            status_code = openmtc.exc.STATUS_INTERNAL_SERVER_ERROR

        raise ErrorResponseConfirmation(
            statusCode=status_code,
            primitiveType=method,
            errorInfo=response.payload or "<no further information available>")

    def _send_create(self, request_indication, path):
        data = self.__serializer.encode_values(request_indication.typename,
                                               request_indication.resource)
        resp = self.client.post(path, data, content_type="application/json")
        if resp.code >= 100:
            self._raise_error("create", resp)
        return CreateResponseConfirmation(resp.payload)

    def _send_notify(self, request_indication, path):
        data = self.__serializer.encode_values(request_indication.typename,
                                               request_indication.resource)
        resp = self.client.post(path, data, content_type="application/json")
        if resp.code >= 100:
            self._raise_error("notify", resp)
        return NotifyResponseConfirmation()

    def _send_update(self, request_indication, path):
        data = self.__serializer.encode_values(request_indication.typename,
                                               request_indication.resource)
        resp = self.client.put(path, data, content_type="application/json")
        if resp.code >= 100:
            self._raise_error("create", resp)
        return UpdateResponseConfirmation()

    def _send_retrieve(self, request_indication, path):
        resp = self.client.get(path)
        if resp.code >= 100:
            self._raise_error("create", resp)

        return decode_result(request_indication.path, resp.payload,
                             resp.content_format)

    def _send_delete(self, request_indication, path):
        resp = self.client.delete(path)
        if resp.code >= 100:
            self._raise_error("create", resp)
        return DeleteResponseConfirmation()

    def create(self, path, resource):
        return self.send_request_indication(
            CreateRequestIndication(path, resource))

    def update(self, resource, fields=()):
        return self.send_request_indication(
            UpdateRequestIndication(resource.path, resource, fields=fields))

    def retrieve(self, path):
        return self.send_request_indication(RetrieveRequestIndication(path))

    def delete(self, path):
        return self.send_request_indication(DeleteRequestIndication(path))
Ejemplo n.º 5
0
class XIXCoap(LoggerMixin):
    """XIXCoap serializes RequestIndications to CoAP messages and sends them using a CoapClient"""
    def __init__(self,
                 uri,
                 client_port=None,
                 scl_base=None,
                 use_xml=False,
                 keyfile=None,
                 certfile=None,
                 block_size_exponent=10,
                 *args,
                 **kw):
        """Initializes XIXCoap and its underlying CoapClient
        
        :param uri:URI referencing the server this clients is trying to reach. Can contain SCHEME://IP:PORT
        :param client_port: Port used by the client when sending requests
        :param scl_base: Default basename to prefix an SCL resource path
        :param use_xml: Binary parameter swapping between content types of xml and json
        """
        self.client = CoapClient(uri,
                                 client_port or 25682,
                                 keyfile=keyfile,
                                 certfile=certfile,
                                 block_size_exponent=block_size_exponent)
        self.scl_base = scl_base
        self.logger.debug("CoapClient created with uri %s", uri)
        if use_xml:
            from openmtc_etsi.serializer.xml import XMLSerializer as Serializer
            self.content_type = "application/xml"
        else:
            from openmtc_etsi.serializer.json import JsonSerializer as Serializer
            self.content_type = "application/json"
        self.__serializer = Serializer()
        self.methodmappers = {
            "create": self._send_create,
            "notify": self._send_notify,
            "update": self._send_update,
            "delete": self._send_delete,
            "retrieve": self._send_retrieve
        }

    def send_request_indication(self, request_indication):
        """Serializes a RequestIndication to a CoAP message and sends it using a CoapClient
        
        :param request_indication: RequestIndication to be processed
        :return: Corresponding ResponseConfirmation
        """
        if self.scl_base is not None and \
                not request_indication.path.startswith(self.scl_base) and \
                "://" not in request_indication.path:
            request_indication.path = self.scl_base + request_indication.path

        path = request_indication.path
        if path.startswith('/'):
            path = path[1:]

        mapper = self.methodmappers[request_indication.method]
        return mapper(request_indication, path)

    def _raise_error(self, method, response):
        """Handles reponses containing an error status code. Generates an ErrorResponseConfirmation.
        
        :param method: Request method, can be "create", "notify", "update", "delete" or "retrieve"
        :param response: CoAP response
        """
        try:
            status_code = _coap2etsi[response.code]
        except KeyError:
            self.logger.warning("Failed to map coap response code: %s",
                                response.code)
            status_code = openmtc_etsi.exc.STATUS_INTERNAL_SERVER_ERROR
        except AttributeError:
            self.logger.warning("No response for %s", method)
            status_code = openmtc_etsi.exc.STATUS_INTERNAL_SERVER_ERROR

        if response and hasattr(response, "payload"):
            raise ErrorResponseConfirmation(
                statusCode=status_code,
                primitiveType=method,
                errorInfo=response.payload
                or "<no further information available>")
        else:
            raise ErrorResponseConfirmation(
                statusCode=status_code,
                primitiveType=method,
                errorInfo=response or "<no further information available>")

    def _send_create(self, request_indication, path):
        """Serializes a CreateRequestIndication to a CoAP POST message and sends it using a CoapClient
        
        :param request_indication: CreateRequestIndication to be processed
        :param path: Resource path
        :return: Corresponding CreateResponseConfirmation
        """
        if request_indication.content_type:
            data = request_indication.resource
        else:
            data = self.__serializer.encode_values(request_indication.typename,
                                                   request_indication.resource)

        def handle_response(resp):
            if resp.code >= 100:
                self._raise_error("create", resp)
            location = resp.findOption(8)
            if location:
                return CreateResponseConfirmation(location[0].value,
                                                  resp.payload)
            else:
                return CreateResponseConfirmation(resp.payload)

        return self.client.post(
            path, data, content_type=self.content_type).then(handle_response)

    def _send_notify(self, request_indication, path):
        """Serializes a NotifyRequestIndication to a CoAP POST message and sends it using a CoapClient
        
        :param request_indication: NotifyRequestIndication to be processed
        :param path: Resource path
        :return: Corresponding NotifyResponseConfirmation
        """
        if request_indication.content_type:
            data = request_indication.resource
        else:
            data = self.__serializer.encode_values(request_indication.typename,
                                                   request_indication.resource)

        def handle_response(resp):
            if resp.code >= 100:
                self._raise_error("notify", resp)
            return NotifyResponseConfirmation()

        return self.client.post(
            path, data, content_type=self.content_type).then(handle_response)

    def _send_update(self, request_indication, path):
        """Serializes a UpdateRequestIndication to a CoAP POST message and sends it using a CoapClient
        
        :param request_indication: UpdateRequestIndication to be processed
        :param path: Resource path
        :return: Corresponding UpdateResponseConfirmation
        """
        if request_indication.content_type:
            data = request_indication.resource
        else:
            data = self.__serializer.encode_values(request_indication.typename,
                                                   request_indication.resource)

        def handle_response(resp):
            if resp.code >= 100:
                self._raise_error("update", resp)
            return UpdateResponseConfirmation()

        return self.client.put(
            path, data, content_type=self.content_type).then(handle_response)

    def _send_retrieve(self, request_indication, path):
        """Serializes a RetrieveRequestIndication to a CoAP GET message and sends it using a CoapClient
        
        :param request_indication: RetrieveRequestIndication to be processed
        :param path: Resource path
        :return: Corresponding RetrieveResponseConfirmation
        """
        # TODO: Accept must be set dynamically
        self.logger.debug("send retrieve path %s" % path)

        def handle_response(resp):
            if resp.code >= 100:
                self._raise_error("retrieve", resp)
            if resp.code == VALID:
                return RetrieveResponseConfirmation(None)
            else:
                d, ct = decode_result(request_indication.path, resp.payload,
                                      resp.content_format)
            return RetrieveResponseConfirmation(resource=d, content_type=ct)

        return self.client.get(path, accept=50).then(handle_response)

    def _send_delete(self, request_indication, path):
        """Serializes a DeleteRequestIndication to a CoAP DELETE message and sends it using a CoapClient
        
        :param request_indication: DeleteRequestIndication to be processed
        :param path: Resource path
        :return: Corresponding DeleteResponseConfirmation
        """
        def handle_response(resp):
            if not resp or resp.code >= 100:
                self._raise_error("delete", resp)
            else:
                return DeleteResponseConfirmation()

        return self.client.delete(path).then(handle_response)

    def create(self, path, resource):
        """Creates and serializes a CreateRequestIndication to a CoAP POST message and sends it using a CoapClient

        :param path: Resource path
        :param resource: Request payload
        :return: Corresponding CreateResponseConfirmation
        """
        return self.send_request_indication(
            CreateRequestIndication(path, resource))

    def update(self, resource, fields=()):
        """Creates and serializes a UpdateRequestIndication to a CoAP PUT message and sends it using a CoapClient

        :param path: Resource path
        :return: Corresponding UpdateResponseConfirmation
        """
        return self.send_request_indication(
            UpdateRequestIndication(resource.path, resource, fields=fields))

    def retrieve(self, path):
        """Creates and serializes a RetrieveRequestIndication to a CoAP GET message and sends it using a CoapClient

        :param path: Resource path
        :return: Corresponding RetrieveResponseConfirmation
        """
        return self.send_request_indication(RetrieveRequestIndication(path))

    def delete(self, path):
        """Creates and serializes a DeleteRequestIndication to a CoAP DELETE message and sends it using a CoapClient

        :param path: Resource path
        :return: Corresponding DeleteResponseConfirmation
        """
        return self.send_request_indication(DeleteRequestIndication(path))
Ejemplo n.º 6
0
Note that coap:// is mandatory here
"""
#client = CoapClient("coap://ns.tzi.org:61616")
client = CoapClient("coap://localhost:5684")
"""
Some example of requests, the return is always a promise object
1st param: ressource path
2nd param: payload
Optional params: 'content_type', 'max_age', 'uri_scheme', 'etag', 'uri_authority', 'location'
"""
#p=client.post("sink","data")
#p=client.put("rd?ep=test","data")
#p=client.delete("ressource_name")
p = client.post("rd?ep=node1&lt=4500&version=1&binding=U", "3/1/1, 4/1/2")
#p=client.post("rd?ep=node2&lt=9000&version=5&binding=UP","3/2/2")
p = client.get("rd?ep=node1")
#&lt=4500&version=1&binding=U"
#, content_type='JSON'

#This fails:
#p=client.get("mes")
#This works:
#p=client.get("res")
"""
Generic request format
Supported methods: GET POST PUT DELETE
"""
#p=client.request("GET","path")
#p=client.request("PUT","path","data")
"""
Processing of the Promise with a simple handler