CoAP is lightweight and its implementation both on a client and server basis should take few resources. Here, we use the Python-based aiocoap library. More can be read on aiocoap in: Amsüss, Christian, and Wasilak, Maciej. aiocoap: Python CoAP Library. Energy Harvesting Solutions, 2013–. http://github.com/chrysn/aiocoap/. Many other free CoAP clients and servers exist with several written in low-level C code for extremely constrained sensor environments. Here, we use a Python environment for brevity.
The client implementation is:
#!/usr/bin/env python3
import asyncio #necessary for asynchronous processing in Python
from aiocoap import * #using the aiocoap library
The following is main loop for the client. The client uses PUT to broadcast the temperature to known URI:
async def main():
context = await Context.create_client_context()
await asyncio.sleep(2) #wait 2 seconds after initialization
payload = b"20.2 C"
request = Message(code=PUT, payload=payload)
request.opt.uri_host = '127.0.0.1' #URI for localhost address
request.opt.uri_path = ("temp", "celcius") #URI for path to /temp/celcius
response = await context.request(request).response
print('Result: %s %r'%(response.code, response.payload))
if __name__ == "__main__":
asyncio.get_event_loop().run_until_complete(main())
The server implementation is:
#!/usr/bin/env python3
import asyncio #necessary for asynchronous processing in Python
import aiocoap.resource as resource #using aiocoap library
import aiocoap
The following code illustrates the services for PUT and GET methods:
class GetPutResource(resource.Resource):
def __init__(self):
super().__init__()
self.set_content(b"Default Data (padded) "
def set_content(self, content): #Apply padding
self.content = content
while len(self.content) <= 1024:
self.content = self.content + b"0123456789 "
async def render_get(self, request): #GET handler
return aiocoap.Message(payload=self.content)
async def render_put(self, request): #PUT handler
print('PUT payload: %s' % request.payload)
self.set_content(request.payload) #replaces set_content with received payload
return aiocoap.Message(code=aiocoap.CHANGED, payload=self.content) #set response code to 2.04
The main loop is:
def main():
root = resource.Site() #root element that contains all resources found on server
root.add_resource(('.well-known', 'core'), #this is the typical .well-known/core
resource.WKCResource(root.get_resources_as_linkheader)) #resource list for .well-known/core
root.add_resource(('temp', 'celcius'), GetPutResource())) #adds the resource /tmp/celcius
asyncio.Task(aiocoap.Context.create_server_context(root))
asyncio.get_event_loop().run_forever()
if __name__ == "__main__":
main()