def client_registration_update(self, server_ip, server_port, path, query, payload, \
                                client_port=5683, client=None):
     server_ip_port = server_ip + ":" + str(server_port)
     path_query = str(path)  + "?" + query
     payload = payload
     if client is None:
         client = CoapClient("coap://" + server_ip_port, client_port=client_port)
     result = client.put(path_query,  payload, timeout=10000)
     
     return result
 def write_attributes(self, server_ip, server_port, endpoint_name, object_id, payload, content_type,
                     object_inst_id=None, res_id=None, res_inst_id=None, client_port=5683):
     
     server_ip_port = server_ip + ":" + str(server_port)
     query = "?method=write_attributes"
     path = "rd/" + endpoint_name + "/" + 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 None:
                 res_inst_id = 0
             path += "/" + str(res_inst_id)
     
     path += query
     client = CoapClient("coap://" + server_ip_port, client_port=client_port)
     result = client.put(path, payload, timeout=10000, content_type=content_type)
     
     return result
 def write_resource(self, server_ip, server_port, endpoint_name, object_id, \
                    payload, content_type, object_inst_id=None, res_id=None, \
                    res_inst_id=None, client_port=5683):
     
     query = "?method=write"
     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"
     
     path += query
     
     client = CoapClient("coap://" + server_ip_port, client_port=client_port)
     result = client.put(path, payload, timeout=10000, content_type=content_type)
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))
Esempio 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))