Description
- Update the Python module named
CoapClientConnector with support for DELETE requests, using the existing method definitions within IRequestResponseHandler to support this request type.
- NOTE: These instructions make use of the following CoAP library:
- The aiocoap open source CoAP library, located at: aiocoap. Reference: Amsüss, Christian and Wasilak, Maciej. aiocoap: Python CoAP Library. Energy Harvesting Solutions, 2013–. http://github.com/chrysn/aiocoap/.
Review the README
- Please see README.md for further information on, and use of, this content.
- License for embedded documentation and source codes: PIOT-DOC-LIC
Estimated effort may vary greatly
- The estimated level of effort for this exercise shown in the 'Estimate' section below is a very rough approximation. The actual level of effort may vary greatly depending on your development and test environment, experience with the requisite technologies, and many other factors.
Actions
Step 1: Create and implement a callable DELETE request method
- Implement the public
sendDeleteRequest() method
- This method will take the following arguments:
- resource (
ResourceNameEnum): Used to create the general request URL
- name (
str): Used to extend the general request URL with further detail (if warranted)
- enableCON (
bool): If True, use a CONFIRMABLE request; else, use NONCONFIRMABLE
- timeout (
int): The timeout value to pass to the CoAP client infrastructure
- A general implementation may look like the following:
def sendDeleteRequest(self, resource: ResourceNameEnum = None, name: str = None, enableCON: bool = False, timeout: int = IRequestResponseClient.DEFAULT_TIMEOUT) -> bool:
if resource or name:
resourcePath = self._createResourcePath(resource, name)
logging.info(f"Issuing Async DELETE to path: {resourcePath}")
future = asyncio.run_coroutine_threadsafe(
self._handleDeleteRequest(resourcePath, enableCON),
self._eventLoopThread
)
return future.result()
else:
logging.warning("Can't issue Async DELETE - no path provided.")
Step 2: Create and implement the internal DELETE request callback method and response handler
- Implement the internal
_handleDeleteRequest() and _onDeleteResponse() methods
- These methods will process the incoming response from the CoAP server, parse the payload, determine which data type is part of the payload, and react accordingly.
_handleDeleteRequest() will take the following arguments:
- resourcePath (
str): This will be the full resource path used for the request
- enableCON (
bool): If True, use a CONFIRMABLE request; else, use NONCONFIRMABLE
- A general implementation may look like the following:
async def _handleDeleteRequest(self, resourcePath: str = None, enableCON: bool = False):
try:
uriAndResourcePath = self.uriPath + resourcePath
msgType = NON
if enableCON:
msgType = CON
msg = Message(mtype = msgType, code = Code.DELETE, uri = uriAndResourcePath)
responseData = await self.clientContext.request(request_message = msg).response
self._onDeleteResponse(responseData)
- The
_onDeleteResponse() method is rather simple - it decodes the incoming payload and logs it to the console.
def _onDeleteResponse(self, response):
if not response:
logging.warning("Async DELETE response invalid. Ignoring.")
return
logging.info("Async DELETE response received.")
responseData = response.payload.decode("utf-8")
logging.info(f"Response data received. Payload: {responseData}")
Estimate
Tests
- Edit / add test cases
- Update the
test_CoapAsyncClientConnectorTest.py module (containing the CoapAsyncClientConnectorTest class) in CDA_HOME/tests/integration/connection as indicated below.
- If not already done for you within the code, disable the existing tests by UNCOMMENTING the skip test annotation before each test case (change
#@unittest.skip("Ignore for now.") to @unittest.skip("Ignore for now.")).
- If not already done for you within the code, create a two tests to issue a
SensorData delete request to the CoAP server using both CON and NON requests.
- The code for each should look similar to the following:
@unittest.skip("Ignore for now.")
def testDeleteSensorMessageCon(self):
self.coapClient.sendDeleteRequest( \
resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, enableCON = True, timeout = 5)
@unittest.skip("Ignore for now.")
def testDeleteSensorMessageNon(self):
self.coapClient.sendDeleteRequest( \
resource = ResourceNameEnum.CDA_SENSOR_MSG_RESOURCE, enableCON = False, timeout = 5)
- Setup
- Start Wireshark, and ensure it's watching the loopback adapter.
- You can filter on 'coap' to track only CoAP messages, which is recommended for this test.
- Start your GDA application with the CoAP server enabled. Make sure it runs for a couple of minutes - long enough for you to run the integration tests listed below.
- To run your GDA from the command line, you just need to do the following from a shell (assuming you're starting from the parent directory containing your java-components, and that the path is named 'piot-java-components':
- NOTE: Be sure to run your GDA Java app for a few minutes so you have time to run the tests!!
cd piot-java-components
mvn clean install -DskipTests
java -jar target/gateway-device-app-0.0.1-jar-with-dependencies.jar
- Run the DELETE tests
- Run both
testDeleteSensorMessage...() test cases and watch the output in the console for the client as well as within Wireshark.
- NOTE: If you're a student in the Connected Devices course, be sure to follow the instructions in PIOT-INF-09-003.
- Your output will contain log content similar to the following - and be sure to notice the WARNING message at the end:
About the WARNING message
- Recall that the GDA CoAP server implementation for handling CDA SensorData messages (via the
UpdateTelemetryResourceHandler only implements the PUT request, and NOT DELETE (or POST or GET).
- You can choose to add the DELETE handler within
UpdateTelemetryResourceHandler, which will then generate log output similar to that of the PUT functionality.
Description
CoapClientConnectorwith support for DELETE requests, using the existing method definitions withinIRequestResponseHandlerto support this request type.Review the README
Estimated effort may vary greatly
Actions
Step 1: Create and implement a callable DELETE request method
sendDeleteRequest()methodResourceNameEnum): Used to create the general request URLstr): Used to extend the general request URL with further detail (if warranted)bool): If True, use a CONFIRMABLE request; else, use NONCONFIRMABLEint): The timeout value to pass to the CoAP client infrastructureStep 2: Create and implement the internal DELETE request callback method and response handler
_handleDeleteRequest()and_onDeleteResponse()methods_handleDeleteRequest()will take the following arguments:str): This will be the full resource path used for the requestbool): If True, use a CONFIRMABLE request; else, use NONCONFIRMABLE_onDeleteResponse()method is rather simple - it decodes the incoming payload and logs it to the console.Estimate
Tests
test_CoapAsyncClientConnectorTest.pymodule (containing theCoapAsyncClientConnectorTestclass) in CDA_HOME/tests/integration/connection as indicated below.#@unittest.skip("Ignore for now.")to@unittest.skip("Ignore for now.")).SensorDatadelete request to the CoAP server using both CON and NON requests.testDeleteSensorMessage...()test cases and watch the output in the console for the client as well as within Wireshark.About the WARNING message
UpdateTelemetryResourceHandleronly implements the PUT request, and NOT DELETE (or POST or GET).UpdateTelemetryResourceHandler, which will then generate log output similar to that of the PUT functionality.