{"id":15163270,"url":"https://github.com/insighio/microcoapy","last_synced_at":"2025-10-25T02:30:32.230Z","repository":{"id":44634059,"uuid":"208242855","full_name":"insighio/microCoAPy","owner":"insighio","description":"A mini client/server implementation of CoAP (Constrained Application Protocol) into MicroPython","archived":false,"fork":false,"pushed_at":"2024-02-26T08:39:36.000Z","size":70,"stargazers_count":59,"open_issues_count":5,"forks_count":12,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-10-30T00:36:08.694Z","etag":null,"topics":["client","coap","coap-client","coap-server","esp32","esp8266","micropython","pycom","server"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/insighio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-09-13T10:28:30.000Z","updated_at":"2024-10-23T17:54:52.000Z","dependencies_parsed_at":"2024-01-07T21:53:21.286Z","dependency_job_id":"c216422e-6245-46ad-9c34-2b85eb954f31","html_url":"https://github.com/insighio/microCoAPy","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insighio%2FmicroCoAPy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insighio%2FmicroCoAPy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insighio%2FmicroCoAPy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/insighio%2FmicroCoAPy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/insighio","download_url":"https://codeload.github.com/insighio/microCoAPy/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238059129,"owners_count":19409601,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["client","coap","coap-client","coap-server","esp32","esp8266","micropython","pycom","server"],"created_at":"2024-09-27T02:22:16.776Z","updated_at":"2025-10-25T02:30:32.219Z","avatar_url":"https://github.com/insighio.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# microCoAPy\n\nA mini implementation of CoAP (Constrained Application Protocol) into MicroPython\n\nThe main difference compared to the established Python implementations [aiocoap](https://github.com/chrysn/aiocoap) and [CoAPthon](https://github.com/Tanganelli/CoAPthon) is its size and complexity since this library will be used on microcontrollers that support MicroPython such as: Pycom devices, ESP32, ESP8266.\n\nThe first goal of this implementation is to provide basic functionality to send and receive data. DTLS and/or any special features of CoAP as defined in the RFC's, will be examined and implemented in the future.\n\n# Table of contents\n\n- [Tested boards](#tested-boards)\n- [Documentation](https://github.com/insighio/microCoAPy/wiki)\n- [Installation](#installation)\n- [Supported operations](#supported-operations)\n  - [CoAP client](#coap-client)\n    - [Example of usage](#example-of-usage)\n      - [Code explained](#code-explained)\n  - [CoAP server](#coap-server)\n    - [Example of usage](#example-of-usage-1)\n      - [Code explained](#code-explained-1)\n  - [Custom sockets](#custom-sockets)\n  - [Pycom custom socket based on AT commands](#pycom-custom-socket-based-on-at-commands)\n- [Beta features under implementation or evaluation](#beta-features-under-implementation-or-evaluation)\n  - [Discard incoming retransmission](#discard-incoming-retransmission)\n  - [Activate debug messages](#activate-debug-messages)\n- [Future work](#future-work)\n- [Issues and contributions](#issues-and-contributions)\n\n# Tested boards\n\n- Pycom: all Pycom boards\n- ESP32\n- ESP8266\n\n# Installation\n\n## Using `mip`\n\nFor network connected devices, call:\n\n```\nimport mip\nmip.install(\"github:insighio/microCoAPy\")\n```\n\n## File Transfer\n\nDownload and transfer files in the board through [ampy](https://pypi.org/project/adafruit-ampy/).\n\n# Supported operations\n\n## CoAP client\n\n- PUT\n- POST\n- GET\n\n### Example of usage\n\nHere is an example using the CoAP client functionality to send requests and receive responses. (this example is part of [examples/pycom_wifi_coap_client.py](https://github.com/insighiot/microCoAPy/blob/master/examples/pycom_wifi_coap_client.py))\n\n```python\nimport microcoapy\n# your code to connect to the network\n#...\ndef receivedMessageCallback(packet, sender):\n        print('Message received:', packet.toString(), ', from: ', sender)\n        print('Message payload: ', packet.payload.decode('unicode_escape'))\n\nclient = microcoapy.Coap()\nclient.responseCallback = receivedMessageCallback\nclient.start()\n\n_SERVER_IP=\"192.168.1.2\"\n_SERVER_PORT=5683\nbytesTransferred = client.get(_SERVER_IP, _SERVER_PORT, \"current/measure\")\nprint(\"[GET] Sent bytes: \", bytesTransferred)\n\nclient.poll(2000)\n\nclient.stop()\n```\n\n#### Code explained\n\nLets examine the above code and explain its purpose.\n\n```python\ndef receivedMessageCallback(packet, sender):\n        print('Message received:', packet.toString(), ', from: ', sender)\n        print('Message payload: ', packet.payload.decode('unicode_escape'))\n\nclient = microcoapy.Coap()\nclient.responseCallback = receivedMessageCallback\n```\n\nDuring this step, the CoAP object get initialized. A callback handler is also created to get notifications from the server regarding our requests. **It is not used for incoming requests.**\n\nWhen instantiating new Coap object, a custom port can be optionally configured: _client = microcoapy.Coap(5683)_.\n\n```python\nclient.start()\n```\n\nThe call to the [_start_](https://github.com/insighio/microCoAPy/wiki#startport) function is where the UDP socket gets created. By default it gets bind to the default CoAP port 5683. If a custom port is required, pass it as argument to the [_start_](https://github.com/insighio/microCoAPy/wiki#startport) function.\n\n```python\nbytesTransferred = client.get(_SERVER_IP, _SERVER_PORT, \"current/measure\")\nprint(\"[GET] Sent bytes: \", bytesTransferred)\n```\n\nHaving the socket ready, it is time to send our request. In this case we send a simple GET request to the specific address (ex. 192.168.1.2:5683). The [_get_](https://github.com/insighio/microCoAPy/wiki#getip-port-url) function returns the number of bytes that have been sent. So in case of error, 0 will be returned.\n\n```python\nclient.poll(2000)\n```\n\nSince a GET request has been posted, most likely it would be nice to receive and process the server response. For this reason we call [_poll_](https://github.com/insighio/microCoAPy/wiki#polltimeoutms-pollperiodms) function that will try to read incoming messages for 2000 milliseconds. Upon timeout the execution will continue to the next command.\n\nIf a packet gets received during that period of type that is an _ACK_ to our request or a report (ex. _404_), the callback that has been registered at the beginning will be called.\n\n```python\nclient.stop()\n```\n\nFinally, stop is called to gracefully close the socket. It is preferable to have a corresponding call of [_stop_](https://github.com/insighio/microCoAPy/wiki#stop) to each call of [_start_](https://github.com/insighio/microCoAPy/wiki#startport) function because in special cases such as when using mobile modems, the modem might stuck when running out of available sockets.\n\nTo send POST or PUT message replace the call of _get_ function with:\n\n```python\nbytesTransferred = client.put(_SERVER_IP, _SERVER_PORT, \"led/turnOn\", \"test\",\n                                 None, microcoapy.COAP_CONTENT_FORMAT.COAP_TEXT_PLAIN)\n```\n\nor\n\n```python\nbytesTransferred = client.post(_SERVER_IP, _SERVER_PORT, \"led/turnOn\", \"test\",\n                                 None, microcoapy.COAP_CONTENT_FORMAT.COAP_TEXT_PLAIN)\n```\n\nFor details on the arguments please advice the [documentation](https://github.com/insighio/microCoAPy/wiki).\n\n## CoAP server\n\nStarts a server and calls custom callbacks upon receiving an incoming request. The response needs to be defined by the user of the library.\n\n### Example of usage\n\nHere is an example using the CoAP server functionality to receive requests and respond back. (this example is part of [examples/pycom_wifi_coap_server.py](https://github.com/insighiot/microCoAPy/blob/master/examples/pycom_wifi_coap_server.py))\n\n```python\nimport microcoapy\n# your code to connect to the network\n#...\nclient = microcoapy.Coap()\n\ndef measureCurrent(packet, senderIp, senderPort):\n    print('Measure-current request received: ', packet.toString(), ', from: ', senderIp, \":\", senderPort)\n    client.sendResponse(senderIp, senderPort, packet.messageid,\n                      \"222\", microcoapy.COAP_RESPONSE_CODE.COAP_CONTENT,\n                      microcoapy.COAP_CONTENT_FORMAT.COAP_NONE, packet.token)\n\nclient.addIncomingRequestCallback('current/measure', measureCurrent)\n\nclient.start()\n\n# wait for incoming request for 60 seconds\ntimeoutMs = 60000\nstart_time = time.ticks_ms()\nwhile time.ticks_diff(time.ticks_ms(), start_time) \u003c timeoutMs:\n    client.poll(60000)\n\nclient.stop()\n```\n\n#### Code explained\n\nLets examine the above code and explain its purpose. For details on [_start_](https://github.com/insighio/microCoAPy/wiki#startport) and [_stop_](https://github.com/insighio/microCoAPy/wiki#stop) functions advice the previous paragraph of the client example.\n\n```python\ndef measureCurrent(packet, senderIp, senderPort):\n    print('Measure-current request received: ', packet.toString(), ', from: ', senderIp, \":\", senderPort)\n    client.sendResponse(senderIp, senderPort, packet.messageid,\n                      \"222\", microcoapy.COAP_RESPONSE_CODE.COAP_CONTENT,\n                      microcoapy.COAP_CONTENT_FORMAT.COAP_NONE, packet.token)\n\nclient.addIncomingRequestCallback('current/measure', measureCurrent)\n```\n\nThis is the main step to prepare the CoAP instance to behave as a server: receive and handle requests. First we create a function _measureCurrent_ that takes as arguments the incoming packet, the sender IP and Port. This function will be used as a callback and will be triggered every time a specific URI path is provided in the incoming request.\n\nThis URL is defined upon registering the callback to the CoAP instance by calling [_addIncomingRequestCallback_](https://github.com/insighio/microCoAPy/wiki#addincomingrequestcallbackrequesturl-callback) function. After this call, if a CoAP GET/PUT/POST packet is received with URI path: coap://\u003cIP\u003e/current/measure , the callback will be triggered.\n\nBy default, the server does not send any response. This is a responsibility of the user to send (if needed) the appropriate response.\n\nIn this example, we reply with a response message packet (which has the same message id as the incoming request packet) whose payload is the actual value of the reading that has just been executed (in the example it is a hard-coded value of 222).\n\n```python\ntimeoutMs = 60000\nstart_time = time.ticks_ms()\nwhile time.ticks_diff(time.ticks_ms(), start_time) \u003c timeoutMs:\n    client.poll(60000)\n```\n\nFinally, since the functions [_loop_](https://github.com/insighio/microCoAPy/wiki#loopblocking) and [_poll_](https://github.com/insighio/microCoAPy/wiki#polltimeoutms-pollperiodms) **can handle a since packet per run**, we wrap its call to a while loop and wait for incoming messages.\n\n## Custom sockets\n\nBy using default functions **microcoapy.Coap().start()** and **microcoapy.Coap().stop()** the Coap library handles the creation of a UDP socket from **usocket module** at the default port 5683 (if no other is defined when Coap object gets instantiated).\n\nIf this socket type is not the appropriate for your project, custom socket instances can be used instead.\n\nLets consider the case of supporting an external GSM modem connected via Serial on the board and that there is no direct support of this modem from default modules like **network.LTE**. In this case there is no guarranty that a typical UDP socket from usocket module will be functional. Thus, a custom socket instance needs to be created.\n\nThe custom socket needs to implement the functions:\n\n- sendto(self, bytes, address) : returns the number of bytes transmitted\n- recvfrom(self, bufsize): returns a byte array\n- setblocking(self, flag)\n\nExample:\n\n```python\n## Custom socket implementation\nclass CustomSocket:\n    def __init__(self):\n        print(\"CustomSocket: init\")\n\n    def sendto(self, bytes, address):\n        print(\"CustomSocket: Sending bytes to: \" + str(address))\n        return len(bytes)\n\n    def recvfrom(self, bufsize):\n        print(\"CustomSocket: receiving max bytes: \" + bufsize)\n        return b\"test data\"\n\n    def setblocking(self, flag):\n        print(\".\", end=\"\")\n```\n\nAfter creating the custom socket, it is utilized by the Coap instance after calling [microcoapy.Coap.setCustomSocket(customSocket)](https://github.com/insighio/microCoAPy/wiki#setcustomsocketcustom_socket).\n\nExample:\n\n```python\nclient = microcoapy.Coap()\n# setup callback for incoming response to a request\nclient.responseCallback = receivedMessageCallback\n\n# Initialize custom socket\ncustomSocket = CustomSocket()\n\n# Use custom socket to all operations of CoAP\nclient.setCustomSocket(customSocket)\n```\n\n## Pycom custom socket based on AT commands\n\nSince most of the implementations of NBIoT networks are based on IPv6, it was essential to move to a custom implementation of UDP socket, as Pycom do not yet support natively IPv6 sockets. Thus, in [examples/pycom/nbiot/pycom_at_socket.py](https://github.com/insighio/microCoAPy/blob/master/examples/pycom/nbiot/pycom_at_socket.py) you can find a complete implementation of a sample socket that directly uses Sequans AT commands.\n\nNOTE: The socket to work without limitations needs one of the following Pycom firmwares:\n\n- [Pygate Firmware Release v1.20.2.rc11](https://github.com/pycom/pycom-micropython-sigfox/releases/tag/v1.20.2.rc11_pygate) (or newer)\n- [Firmware Release v1.20.2.r1](https://github.com/pycom/pycom-micropython-sigfox/releases/tag/v1.20.2.r1) (or newer)\n\n# Beta features under implementation or evaluation\n\n## Discard incoming retransmission\n\nIf a received message is the same as the previously message received, it can be discarded. In that case, the poll function will not return at the time of retrieval and will continue to listen for futher incomming messages. Finally the defined responseCallback will not be called.\n\nBy default this simplistic feature is disabled. To enable:\n\n```python\nclient = microcoapy.Coap()\nclient.discardRetransmissions = True\n```\n\n## Activate debug messages\n\nBy default, debug prints in microcoapy are enabled. Though, the user can deactivate the prints per Coap instance:\n\n```python\nclient = microcoapy.Coap()\nclient.debug = False\n```\n\n# Future work\n\n- Since this library is quite fresh, the next period will be full of testing.\n- enhancments on funtionality as needed\n\n# Issues and contributions\n\nIt would be our pleasure to receive comments, bug reports and/or contributions. To do this use the Issues and Pull requests of GitHub.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsighio%2Fmicrocoapy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finsighio%2Fmicrocoapy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finsighio%2Fmicrocoapy/lists"}