programming-the-iot / book-exercise-tasks

This repo is for issues / tasks ONLY. All programming and related exercises for each chapter of 'Programming the Internet of Things' are listed here.
Other
11 stars 12 forks source link

PIOT-CDA-08-004: Update CoapServerAdapter and DeviceDataManager to register all required resource handlers #150

Open labbenchstudios opened 3 years ago

labbenchstudios commented 3 years ago

Description

Review the README

Estimated effort may vary greatly

IMPORTANT NOTE

Actions - for CoapServerAdapter

Using aiocoap (NOTE: only tested on Ubuntu 21.10)

def _initServer(self):
    try:
        # Resource tree creation - lib-specific (this next line of code assumes use of aiocoap)
        self.rootResource = resource.Site()

        self.rootResource.add_resource( \
            ['.well-known', 'core'], \
            resource.WKCResource(self.rootResource.get_resources_as_linkheader))

        self.addResource( \
            resourcePath = ResourceNameEnum.CDA_ACTUATOR_CMD_RESOURCE, \
            endName = ConfigConst.HUMIDIFIER_ACTUATOR_NAME, \
            resource = UpdateActuatorResourceHandler(dataMsgListener = self.dataMsgListener))

        # TODO: add other actuator resource handlers (for HVAC, etc.)

        sysPerfDataListener = GetSystemPerformanceResourceHandler()

        self.addResource( \
            resourcePath = ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, \
            resource = sysPerfDataListener)

        # TODO: add other telemetry resource handlers (for SensorData)

        # register the callbacks with the data message listener instance
        self.dataMsgListener.setSystemPerformanceDataListener(listener = sysPerfDataListener)

        logging.info("Created CoAP server with default resources.")
    except Exception as e:
        traceback.print_exception(type(e), e, e.__traceback__)
        logging.warning("Failed to create CoAP server.")

Using CoAPthon3

def _initServer(self):
    try:
        self.coapServer = CoAP(server_address = (self.host, self.port))

        self.addResource( \
            resourcePath = ResourceNameEnum.CDA_ACTUATOR_CMD_RESOURCE, \
            endName = ConfigConst.HUMIDIFIER_ACTUATOR_NAME, \
            resource = UpdateActuatorResourceHandler(dataMsgListener = self.dataMsgListener))

        # TODO: add other actuator resource handlers (for HVAC, etc.)

        sysPerfDataListener = GetSystemPerformanceResourceHandler()

        self.addResource( \
            resourcePath = ResourceNameEnum.CDA_SYSTEM_PERF_MSG_RESOURCE, \
            resource = sysPerfDataListener)

        # TODO: add other telemetry resource handlers (for SensorData)

        # TODO: register the callbacks with the data message listener instance

        logging.info("Created CoAP server with default resources.")
    except Exception as e:
        traceback.print_exception(type(e), e, e.__traceback__)
        logging.warning("Failed to create CoAP server.")

Using aiocoap

def addResource(self, resourcePath: ResourceNameEnum = None, endName: str = None, resource = None):
    if resourcePath and resource:
        uriPath = resourcePath.value

        if endName:
            uriPath = uriPath + '/' + endName

        resourceList = uriPath.split('/')

        if not self.rootResource:
            self.rootResource = resource.Site()

        self.rootResource.add_resource(resourceList, resource)
    else:
        logging.warning("No resource provided for path: " + uriPath)

Using CoAPthon3

def addResource(self, resourcePath: ResourceNameEnum = None, endName: str = None, resource = None):
    if resourcePath and resource:
        uriPath = resourcePath.value

        if endName:
            uriPath = uriPath + '/' + endName
            resource.name = endName

        trimmedUriPath   = uriPath.strip("/")
        resourceList     = trimmedUriPath.split("/")
        resourceTree     = None
        registrationPath = ""
        generationCount  = 0

        for resourceName in resourceList:
            generationCount = generationCount + 1
            registrationPath = registrationPath + "/" + resourceName

            try:
                resourceTree = self.coapServer.root[registrationPath]
            except KeyError:
                resourceTree = None

        if not resourceTree:
            if len(resourceList) != generationCount:
                return None

            resource.path = registrationPath
            self.coapServer.root[registrationPath] = resource
    else:
        logging.warning("No resource provided for path: " + str(resourcePath.value))

Estimate (Small = < 2 hrs; Medium = 4 hrs; Large = 8 hrs)

Tests

Gau17 commented 7 months ago

Dear Professor Andy,

I discovered an issue in the premade CoapServerAdapterTest given to us as part of the initial codebase.

Line 204 in coapServerAdapterTest is sysPerfData.setMemoryUtilization(sysPerfData) This is causing a recursion issue (can be seen when line 207 is uncommented) when the to_string method is called because the object is directly passed to the method as the memory utilization rather than an actual value.

I think it might be a typo and that the intent was for the code to be this: sysPerfData.setMemoryUtilization(sysPerfVal)

Request you to recheck and update the test case.

Thanks, Gautam

labbenchstudios commented 7 months ago

Good catch. This is now fixed / pushed to the GitHub repo.