Exemple #1
0
    async def render_post(self, request):
        payload = request.payload.decode()
        print(f'LED {self.pin}: POST {payload}')

        if payload in ['0', 'off']:
            self.resource.off()
        elif payload in ['1', 'on']:
            self.resource.on()
        elif payload in ['-1', 'toggle']:
            self.resource.toggle()
        elif 'blink' in payload:
            p = payload.split(" ")
            if p[0] != 'blink':
                return Message(code=Code.BAD_REQUEST)

            on_time, off_time, n = 1, 1, None
            if len(p) > 1 and p[1].isdigit():
                on_time = int(p[1])
            if len(p) > 2 and p[2].isdigit():
                off_time = int(p[2])
            if len(p) > 3 and p[3].isdigit():
                n = int(p[3])

            self.resource.blink(on_time, off_time, n)
        else:
            return Message(code=Code.BAD_REQUEST)
        return Message(code=Code.CHANGED)
Exemple #2
0
 async def render_get(self, request):
     if request.opt.accept == 41:
         return Message(payload=("<data>%s</data>" %
                                 self.text).encode('utf8'),
                        content_format=41)
     else:
         return Message(payload=self.text.encode('utf8'), content_format=0)
Exemple #3
0
    async def render_post(self, request):
        payload = request.payload.decode()
        print(f'SERVO {self.pin}: POST {payload}')
        if self.min_angle <= int(payload) <= self.max_angle:
            self.resource.angle = int(payload)
            return Message(code=Code.CHANGED)

        return Message(code=Code.BAD_REQUEST)
Exemple #4
0
 def abort(self, errormessage=None, bad_csm_option=None):
     self.log.warning("Aborting connection: %s", errormessage)
     abort_msg = Message(code=ABORT)
     if errormessage is not None:
         abort_msg.payload = errormessage.encode('utf8')
     if bad_csm_option is not None:
         bad_csm_option_option = optiontypes.UintOption(2, bad_csm_option)
         abort_msg.opt.add_option(bad_csm_option_option)
     self._abort_with(abort_msg)
	def wraps(self: BaseResource, request: Message):
		try:
			request.payload = gzdecompress(request.payload)
		except OSError:
			# Since the received message was not properly compressed, return a non compressed response just in case
			return Message(code=Code.BAD_REQUEST, payload=b'{"error":"Bad GZIP compression"}')
		
		response = func(self, request)
		response.payload = gzcompress(response.payload)
		return response
Exemple #6
0
    async def render_post(self, request):
        payload = request.payload.decode()
        print(f'GPIO {self.pin}: POST {payload}')

        if payload in ['0', 'off']:
            self.resource.off()
        elif payload in ['1', 'on']:
            self.resource.on()
        else:
            return Message(code=Code.BAD_REQUEST)

        return Message(code=Code.CHANGED)
Exemple #7
0
def _decode_message(data: bytes) -> Message:
    tokenoffset, tkl, _ = _extract_message_size(data)
    if tkl > 8:
        raise error.UnparsableMessage("Overly long token")
    code = data[tokenoffset - 1]
    token = data[tokenoffset:tokenoffset + tkl]

    msg = Message(code=code, token=token)

    msg.payload = msg.opt.decode(data[tokenoffset + tkl:])

    return msg
Exemple #8
0
def _decode_message(data: bytes) -> Message:
    tokenoffset, tkl, _ = _extract_message_size(data)
    if tkl > 8:
        raise error.UnparsableMessage("Overly long token")
    code = data[tokenoffset - 1]
    token = data[tokenoffset:tokenoffset + tkl]

    msg = Message(code=code, token=token)

    msg.payload = msg.opt.decode(data[tokenoffset + tkl:])

    return msg
Exemple #9
0
def _decode_message(data: bytes) -> Message:
    codeoffset = 1
    tokenoffset = 2

    tkl = data[0]
    if tkl > 8:
        raise error.UnparsableMessage("Overly long token")
    code = data[codeoffset]
    token = data[tokenoffset:tokenoffset + tkl]

    msg = Message(code=code, token=token)

    msg.payload = msg.opt.decode(data[tokenoffset + tkl:])

    return msg
Exemple #10
0
    async def start(self):
        p = argparse.ArgumentParser()
        p.add_argument("rd_uri", help="Preconfigured address of the resource"
                " directory", nargs='?', default='coap://[ff05::fd]')
        p.add_argument("--simple", help="Run simple registration rather than"
                " full (incomplete: Never renews)", action="store_true")
        p.add_argument("--register-as", help="Endpoint name to register as (default: node$SITE",
                default=None)
        p.add_argument("--site", help="Use a different resource / link layout", default=1, type=int)
        add_server_arguments(p)

        opts = p.parse_args()

        if opts.site == 1:
            site = build_site_node1()
        elif opts.site == 2:
            site = build_site_node2()
        elif opts.site == 3:
            site = build_site_node3()
        else:
            raise p.error("Invalid site value")

        if opts.register_as is None:
            opts.register_as = "node%s" % opts.site

        self.context = await server_context_from_arguments(site, opts)

        if opts.simple:
            rd_wkc = urljoin(opts.rd_uri, '/.well-known/core?ep=%s&lt=6000' % opts.register_as)
            await self.context.request(Message(code=POST, uri=rd_wkc)).response
        else:
            self.registerer = Registerer(self.context, opts.rd_uri, lt=120,
                    registration_parameters={'ep': opts.register_as})
    async def _observe(self, api_command: Command[T],
                       timeout: float | None) -> None:
        """Observe an endpoint."""
        duration = api_command.observe_duration
        url = api_command.url(self._host)
        err_callback = api_command.err_callback

        msg = Message(code=Code.GET, uri=url, observe=duration)

        # Note that this is necessary to start observing
        pr_req, pr_rsp = await self._get_response(msg, timeout)

        api_command.process_result(_process_output(pr_rsp))

        def success_callback(res: Message) -> None:
            api_command.process_result(_process_output(res))

        def error_callback(exc: Exception) -> None:
            if isinstance(exc, LibraryShutdown):
                _LOGGER.debug("Protocol is shutdown, stopping observation")
                return

            if err_callback:
                err_callback(exc)

        observation = pr_req.observation
        # The observation is set on the request
        # since we pass a Message with observe set above.
        assert observation is not None
        observation.register_callback(success_callback)
        observation.register_errback(error_callback)
        self._observations_err_callbacks.append(observation.error)
Exemple #12
0
    async def start_rd_observation(uri):
        """ decode Message cbor payload to object """
        def decode_linkformat_payload(payload):
            link = payload.decode('ascii')
            myJson = Parse(link).as_json_string()
            return json.loads(myJson)

        """ start observation of resource """
        def process_resource(resource):
            uris[resource['title']] = resource['href']
            handle = asyncio.create_task(start_node_observation(resource['href'], resource['title']))
            observation_handles.add(handle)

        get_obs_req = Message(code=GET, uri=uri, observe=0)
        request = protocol.request(get_obs_req)
        initResponse = await request.response
        resources = decode_linkformat_payload(initResponse.payload)

        for resource in resources:
            process_resource(resource)

        async for response in request.observation:
            newResources = decode_linkformat_payload(response.payload)
            for resource in newResources:
                process_resource(resource)
Exemple #13
0
    def test_oscore_filebased(self):
        from aiocoap.oscore import FilesystemSecurityContext

        raw = {
            'coap://some-oscore-host/*': {
                'oscore': {
                    'contextfile':
                    __file__.replace('test_credentials.py',
                                     'test_credentials_oscore_context/'),
                    'role':
                    'client'
                }
            },
            'coaps://some-dtls-host/*': {
                'dtls': {
                    'psk': {
                        'hex': '73-65-63-72-65-74-50-53-4b'
                    },
                    'client-identity': b'Client_identity'
                }
            }
        }

        m = CredentialsMap()
        m.load_from_dict(raw)
        message = Message(code=GET,
                          uri='coap://some-oscore-host/.well-known/core')
        secmatch = m.credentials_from_request(message)
        self.assertEqual(type(secmatch), FilesystemSecurityContext)
Exemple #14
0
    def _process_signaling(self, msg):
        if msg.code == CSM:
            if self._remote_settings is None:
                self._remote_settings = {}
            for opt in msg.opt.option_list():
                # FIXME: this relies on the relevant option numbers to be
                # opaque; message parsing should already use the appropriate
                # option types, or re-think the way options are parsed
                if opt.number == 2:
                    self._remote_settings['max-message-size'] = int.from_bytes(opt.value, 'big')
                elif opt.number == 4:
                    self._remote_settings['block-wise-transfer'] = True
                elif opt.number.is_critical():
                    self.abort("Option not supported", bad_csm_option=opt.number)
                else:
                    pass # ignoring elective CSM options
        elif msg.code in (PING, PONG, RELEASE, ABORT):
            # not expecting data in any of them as long as Custody is not implemented
            for opt in msg.opt.option_list():
                if opt.number.is_critical():
                    self.abort("Unknown critical option")
                else:
                    pass

            if msg.code == PING:
                pong = Message(code=PONG, token=msg.token)
                self._send_message(pong)
            elif msg.code == PONG:
                pass
            elif msg.code == RELEASE:
                raise NotImplementedError
            elif msg.code == ABORT:
                raise NotImplementedError
        else:
            self.abort("Unknown signalling code")
Exemple #15
0
async def send_to_coap(payload):
    """
    POST request to:
     localhost
     port 5683 (official IANA assigned CoAP port),
     URI "/other/sensor-values".

    """
    from aiocoap import Context, Message
    from aiocoap.numbers.codes import Code
    from cbor2 import dumps

    context = await Context.create_client_context()

    request = Message(payload=dumps(payload), code=Code.POST)
    request.opt.uri_host = arg_host
    request.opt.uri_port = arg_port
    request.opt.uri_path = ("other", "sensor-values")

    response = await context.request(request).response
    str_res = str(response.code)
    status_code = str_res[:4]  # or str_res.split()[0]
    if status_code == "4.00" or status_code == "5.00":
        print("Error: ", str_res)
        return False

    return True
Exemple #16
0
    async def _observe(self, api_command):
        """Observe an endpoint."""
        duration = api_command.observe_duration
        url = api_command.url(self._host)
        err_callback = api_command.err_callback

        msg = Message(code=Code.GET, uri=url, observe=duration)

        # Note that this is necessary to start observing
        pr, r = await self._get_response(msg)

        api_command.result = _process_output(r)

        def success_callback(res):
            api_command.result = _process_output(res)

        def error_callback(ex):
            if isinstance(ex, LibraryShutdown):
                _LOGGER.debug("Protocol is shutdown, stopping observation")
                return
            err_callback(ex)

        ob = pr.observation
        ob.register_callback(success_callback)
        ob.register_errback(error_callback)
        self._observations_err_callbacks.append(ob.error)
Exemple #17
0
    def _execute(api_command):
        """Execute the command."""
        if api_command.observe:
            yield from _observe(api_command)
            return

        method = api_command.method
        path = api_command.path
        data = api_command.data
        parse_json = api_command.parse_json
        url = api_command.url(host)

        kwargs = {}

        if data is not None:
            kwargs['payload'] = json.dumps(data).encode('utf-8')
            _LOGGER.debug('Executing %s %s %s: %s', host, method, path, data)
        else:
            _LOGGER.debug('Executing %s %s %s', host, method, path)

        api_method = Code.GET
        if method == 'put':
            api_method = Code.PUT

        msg = Message(code=api_method, uri=url, **kwargs)

        try:
            protocol = yield from _get_protocol()
            res = yield from protocol.request(msg).response
        except RequestTimedOut:
            raise RequestTimeout('Request timed out.')

        api_command.result = _process_output(res, parse_json)

        return api_command.result
Exemple #18
0
 async def set_control_values(self, data: dict, retry_count=5, resync=True) -> None:
     state_desired = {
         "state": {
             "desired": {
                 "CommandType": "app",
                 "DeviceId": "",
                 "EnduserId": "",
                 **data,
             }
         }
     }
     payload = json.dumps(state_desired)
     logger.debug("REQUEST: %s", payload)
     payload_encrypted = self._encryption_context.encrypt(payload)
     request = Message(
         code=POST,
         mtype=NON,
         uri=f"coap://{self.host}:{self.port}{self.CONTROL_PATH}",
         payload=payload_encrypted.encode(),
     )
     response = await self._client_context.request(request).response
     logger.debug("RESPONSE: %s", response.payload)
     result = json.loads(response.payload)
     if result.get("status") == "success":
         return True
     else:
         if resync:
             logger.debug("set_control_value failed. resyncing...")
             await self._sync()
         if retry_count > 0:
             logger.debug("set_control_value failed. retrying...")
             return await self.set_control_values(data, retry_count - 1, resync)
         logger.error("set_control_value failed: %s", data)
         return False
Exemple #19
0
 def abort(self, errormessage=None, bad_csm_option=None):
     self.log.warning("Aborting connection: %s", errormessage)
     abort_msg = Message(code=ABORT)
     if errormessage is not None:
         abort_msg.payload = errormessage.encode('utf8')
     if bad_csm_option is not None:
         bad_csm_option_option = optiontypes.UintOption(2, bad_csm_option)
         abort_msg.opt.add_option(bad_csm_option_option)
     if self._transport is not None:
         self._send_message(abort_msg)
         self._transport.close()
     else:
         # FIXME: find out how this happens; i've only seen it after nmap
         # runs against an aiocoap server and then shutting it down.
         # "poisoning" the object to make sure this can not be exploited to
         # bypass the server shutdown.
         self._ctx = None
Exemple #20
0
def start_server():
    protocol = yield from Context.create_client_context()

    request = Message(code = Code.GET, mtype=aiocoap.CON)
    request.set_request_uri('coap://127.0.0.1/button')
    # set observe bit from None to 0
    request.opt.observe = 0

    def handle_notification(response):
        print("asdsadsa")
        print(response)
        import code; code.interact(local=dict(globals(), **locals()))

    protocol_request = protocol.request(request)
    protocol_request.observation.register_callback(handle_notification)
    protocol_request.observation.register_errback(handle_notification)
    response = yield from protocol_request.response
Exemple #21
0
 def abort(self, errormessage=None, bad_csm_option=None):
     self.log.warning("Aborting connection: %s", errormessage)
     abort_msg = Message(code=ABORT)
     if errormessage is not None:
         abort_msg.payload = errormessage.encode('utf8')
     if bad_csm_option is not None:
         bad_csm_option_option = optiontypes.UintOption(2, bad_csm_option)
         abort_msg.opt.add_option(bad_csm_option_option)
     if self._transport is not None:
         self._send_message(abort_msg)
         self._transport.close()
     else:
         # FIXME: find out how this happens; i've only seen it after nmap
         # runs against an aiocoap server and then shutting it down.
         # "poisoning" the object to make sure this can not be exploited to
         # bypass the server shutdown.
         self._ctx = None
Exemple #22
0
async def _get_file(url, method=GET, payload=b''):
    protocol = await Context.create_client_context(loop=None)
    request = Message(code=method, payload=payload)
    request.set_request_uri(url)
    try:
        response = await protocol.request(request).response
    except Exception as e:
        code = "Failed to fetch resource"
        payload = '{}'.format(e)
    else:
        code = response.code
        payload = response.payload
    finally:
        await protocol.shutdown()

    LOGGER.debug('{}: {}'.format(code, payload))
    return code, payload
Exemple #23
0
    def _received_datagram(self, address, datagram):
        try:
            message = Message.decode(datagram, remote=address)
        except error.UnparsableMessage:
            self._log.warning("Ignoring unparsable message from %s", address)
            return

        self._mman.dispatch_message(message)
    async def render(self, request):
        cf = request.opt.content_format
        acc = request.opt.accept
        raise_class = UnallowedMethod
        method_would_have_worked = False

        # FIXME: manually walking the MRO is not a nice way to go about this;
        # is there no other way to query the registered handlers according to
        # the regular inheritance patterns?
        for cls in type(self).mro():
            if not issubclass(
                    cls, ContenttypeRendered) or cls is ContenttypeRendered:
                continue
            for_method = cls.__handlers.get(request.code, None)
            if for_method is None:
                continue
            raise_class = UnsupportedContentFormat
            handler, responseformat = for_method.get((acc, cf), (None, None))
            if handler is not None:
                break
        else:
            raise raise_class()

        sig = inspect.signature(handler)
        parameters = set(sig.parameters.keys())
        parameters.remove("self")
        kwargs = {}
        if request.payload and "payload" not in parameters:
            raise BadRequest("Unexpected payload")
        if request.opt.uri_query and "query" not in parameters:
            raise BadRequest("Unexepcted query arguments")

        for p in parameters:
            if p == "payload":
                kwargs['payload'] = request.payload
            elif p == "request_uri":
                # BIG FIXME: This does not give the expected results due to the
                # URI path stripping in Site, and because Message gets the
                # requested authority wrong on the server side.
                kwargs["request_uri"] = request.get_request_uri()
            else:
                raise RuntimeError("Unexpected argument requested: %s" % p)
        payload = handler(self, **kwargs)

        if payload is None:
            payload = b""
        elif isinstance(payload, str):
            payload = payload.encode('utf8')

        return Message(
            code={
                GET: CONTENT,
                PUT: CHANGED
            }[request.code],
            payload=payload,
            content_format=responseformat,
            no_response=request.opt.no_response,
        )
Exemple #25
0
def _coap_resource(url, method=GET, payload=b''):
    protocol = yield from Context.create_client_context()
    request = Message(code=method, payload=payload)
    request.set_request_uri(url)
    try:
        response = yield from protocol.request(request).response
    except Exception as e:
        code = "Failed to fetch resource"
        payload = '{0}'.format(e)
    else:
        code = response.code
        payload = response.payload.decode('utf-8')
    finally:
        yield from protocol.shutdown()

    logger.debug('Code: {0} - Payload: {1}'.format(code, payload))

    return code, payload
	def _build_msg(code: Code = None, data=None) -> Message:
		"""
		Prepares a `Message` object, adding code and dumping the json data
		"""
		if data is not None:
			payload = json.dumps(data, separators=(',', ':'), ensure_ascii=True).encode('ascii')
		else:
			payload = b''
		return Message(code=code, payload=payload)
    def _received_datagram(self, address, datagram):
        try:
            message = Message.decode(datagram, remote=address)
        except error.UnparsableMessage:
            self._log.warning("Ignoring unparsable message from %s" %
                              (address, ))
            return

        self._new_message_callback(message)
Exemple #28
0
async def send_trigger_request(ctx, target_addr, trigger):
    request = Message(code=Code.POST, mtype=NON, uri="coap://[" + target_addr + "]/t", payload=trigger)

    try:
        response = await ctx.request(request).response
    except Exception as e:
        log("Failed to fetch resource:")
        log(e)
    else:
        log("Trigger result: %s\n%r" % (response.code, response.payload))
Exemple #29
0
async def coap_post(uri, payload):
    """
    Takes in a String URI and a String payload.
    The string is posted to the uri provided.
    (full uri expected e.g. coap://localhost/)
    """
    context = await Context.create_client_context()
    request = Message(code=POST, payload=bytes(payload, 'utf-8'), uri=uri)
    response = await context.request(request).response
    return response
 async def _execute(self, api_command):
     data = api_command.data
     url = api_command.url(self._host)
     kwargs = {}
     kwargs['payload'] = json.dumps(data).encode('utf-8')
     api_method = Code.POST
     msg = Message(code=api_method, uri=url, **kwargs)
     _, res = await self._get_response(msg)
     api_command.result = _process_output(res)
     return api_command.result
Exemple #31
0
    async def get_temperature():
        response = await client.request(
            Message(code=GET,
                    uri=urljoin(args.coap_server,
                                args.temperature_resource))).response

        try:
            return float(response.payload.decode())
        except ValueError:
            return None
Exemple #32
0
 def _send_initial_csm(self):
     my_csm = Message(code=CSM)
     # this is a tad awkward in construction because the options objects
     # were designed under the assumption that the option space is constant
     # for all message codes.
     block_length = optiontypes.UintOption(2, self._my_max_message_size)
     my_csm.opt.add_option(block_length)
     supports_block = optiontypes.UintOption(4, 0)
     my_csm.opt.add_option(supports_block)
     self._send_message(my_csm)