Skip to main content

Using CoAP with Memfault

The Constrained Application Protocol (CoAP) is a UDP-based protocol that is designed to seamlessly interface with HTTP, while accommodating the limitations of constrained devices.

Memfault's servers do not support CoAP directly, but you can use a CoAP-to-HTTP proxy to forward data to Memfault. Alternatively, you can use Golioth, which implements a native Memfault integration for passing data to Memfault.

Golioth

CoAP-enabled devices can communicate with Memfault via Golioth's native Memfault integration, which leverages CoAP and DTLS to provide a single secure connection to the cloud. This ensures that devices are able to access all necessary services without the overhead of establishing multiple connections or including multiple protocol stacks in their firmware.

Memfault data is streamed to Golioth via the Golioth Firmware SDK. It is then routed to Memfault using Golioth Pipelines, which enable projects to filter and transform data before delivering it to a final destination. See the example application for more information on how to set up a pipeline and start sending data to Memfault.

To get started, head over to the Golioth Documentation (and contact us if you have any questions!).

CoAP-to-HTTP Proxy

A CoAP-to-HTTP proxy can be used to forward data from a device to Memfault. The proxy listens for CoAP packets and forwards them to Memfault's servers using HTTP. This approach allows devices to communicate with Memfault without implementing an HTTP client.

A simple example CoAP-HTTP proxy in Python:

coap-proxy.py
# Implement a COAP-to-HTTPs proxy to forward requests to
# https://chunks.memfault.com/api/v0/chunks/

import asyncio
import logging
import os

# Install dependencies:
# pip install aiocoap requests
import aiocoap
import aiocoap.resource as resource
import requests

# Set up logging
logging.basicConfig(
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
level=logging.INFO,
)
LOG = logging.getLogger("coap-proxy")


class ChunkEndpoint(resource.Resource):
"""
Forwards POST requests to Memfault's HTTPs chunks endpoint, and returns the
response, with a hard-coded serial number and Project Key from an
environment variable.
"""
def __init__(self):
super().__init__()

async def render_post(self, request):
LOG.info("POST payload: %s" % repr(request.payload))

coap_payload = request.payload
coap_url = "https://chunks.memfault.com/api/v0/chunks/TEST_SERIAL"

# need to set the Memfault-Project-Key: <YOUR_PROJECT_KEY> header
# to authenticate the request
headers = {
"Memfault-Project-Key": os.getenv("MEMFAULT_PROJECT_KEY"),
"Content-Type": "application/octet-stream",
}

# Forward the COAP request to the HTTPs endpoint
response = requests.post(coap_url, data=coap_payload, headers=headers)

LOG.info("HTTPs response: %s" % response.status_code)
LOG.info("HTTPs response content: %s" % response.content)

# Create a COAP response with the HTTPs response content
return aiocoap.Message(code=aiocoap.CONTENT, payload=response.content)


async def main():
# Resource tree creation
root = resource.Site()

root.add_resource(
[".well-known", "core"], resource.WKCResource(root.get_resources_as_linkheader)
)
root.add_resource(["chunks"], ChunkEndpoint())

await aiocoap.Context.create_server_context(root)

LOG.info("COAP server started")

# Run forever
await asyncio.get_running_loop().create_future()


if __name__ == "__main__":
asyncio.run(main())

When running it, set the MEMFAULT_PROJECT_KEY environment variable to your Project Key.

After starting the server, a request can be issued with the libcoap coap-client tool:

❯ examples/coap-client -m post -f ~/Downloads/chunk_v2_single_chunk_msg-f48b401be2528a137495ab4f8ec2202f.bin 'coap://[::]/chunks'
Accepted

The server will proxy the request and return a response:

❯ MEMFAULT_PROJECT_KEY="<Project Key>" python coap-proxy.py
2024-06-24 16:15:54,104 - coap-proxy - INFO - COAP server started
2024-06-24 16:15:55,391 - coap-proxy - INFO - POST payload: b'\x08\x02\xa7\x02\x01\x03\x01\x07jTESTSERIAL\nmtest-software\tj1.0.0-test\x06mtest-hardware\x04\xa1\x01\xa1rchunk_test_success\x011\xe4'
2024-06-24 16:15:55,535 - coap-proxy - INFO - HTTPs response: 202
2024-06-24 16:15:55,535 - coap-proxy - INFO - HTTPs response content: b'Accepted'