# CoAP Code Examples

> For the complete documentation index, see [llms.txt](https://help.1nce.com/llms.txt).

# CoAP Code Examples

This page provides runnable Node.js code examples for testing the 1NCE OS CoAP endpoints. All examples use the [`node-coap-client`](https://www.npmjs.com/package/node-coap-client) library version 1.0.9.

## Prerequisites

Install the dependency:

```bash
npm install node-coap-client@1.0.9
```

:::tip
On environments where native compilation fails (e.g., Termux/Android), you can install with `--ignore-scripts` since the native crypto module is not used on Node.js >= 10.
:::

## Sending CoAP Messages (POST)

The following script demonstrates sending telemetry data via CoAP POST, with optional DTLS encryption.

```javascript
const coap = require("node-coap-client").CoapClient;

/////// Here you can define if you want to enable or disable DTLS requests ///////
const dtlsEnabled = true; // (optional) Enable/Disable DTLS
//////////////////////////////////////////////////////////////////////////////////

async function coapOnboard(url) {
    await tryToConnectToCoapServer(url);
    const options = {
        keepAlive: true, // Whether to keep the socket connection alive. Speeds up subsequent requests
        confirmable: true, // Whether we expect a confirmation of the request
        retransmit: false, // Whether this message will be retransmitted on loss
    };
    console.log(`Calling CoAP bootstrap endpoint ${url}`);
    const result = await coap.request(url, "get", options);
    const payload = result.payload?.toString();

    if(result.code.toString() !== "2.05") {
        throw new Error(`Error calling CoAP bootstrap endpoint. Result code: ${result.code.toString()}, Payload: ${payload}`);
    }

    console.log(`Boostrap payload: ${payload}`);
    const [clientIdentity, preSharedKey, coapsEndpointUrl] = payload.split(",");

    console.log("===================================");
    console.log("DTLS details:");
    console.log(`Client Identity: ${clientIdentity}`);
    console.log(`Pre-shared key: ${preSharedKey}`);
    console.log(`Coap endpoint: ${coapsEndpointUrl}`);
    console.log("===================================");

    return {
        preSharedKey,
        clientIdentity,
        coapsEndpointUrl
    };
}

function logResponseDetails(res) {
    console.log("=========================================================");
    console.log("Server Response");
    console.log("Status: " + res.code);
    console.log("Payload: " + res.payload.toString());
    console.log("=========================================================");
}

function enableDtls(url, clientIdentity, preSharedKey) {
    coap.setSecurityParams(url, {
        psk: {
            [clientIdentity]: preSharedKey,
        },
    });
}

async function tryToConnectToCoapServer(url) {
    console.log("Trying to connect to CoAP server");
    const res = await coap.tryToConnect(url);
    if (!res) {
        console.error("Connection failed to CoAP server");
        throw Error(`Failed to connect to coap server: ${url}`);
    }

    console.log("Successfully connected to CoAP server");
}

async function sendCoapMessage(url, message) {
    const payload = Buffer.from(message);
    const options = {
        keepAlive: true, // Whether to keep the socket connection alive. Speeds up subsequent requests
        confirmable: true, // Whether we expect a confirmation of the request
        retransmit: false, // Whether this message will be retransmitted on loss
    };

    console.log(`Sending CoAP message to ${url}`)
    const result = await coap.request(
        url, // Server url (string)
        "post", // Request methos ("get" | "post" | "put" | "delete")
        payload, // Request payload (buffer)
        options, // Request options
    );
    logResponseDetails(result);
    const resultPayload = result.payload?.toString();

    if (result.code.toString() !== "2.04") {
        throw new Error(`Error message received from CoAP server. Result code: ${result.code.toString()}, Payload: ${resultPayload}`);
    }

    return {
        code: result.code.toString(),
        message: resultPayload,
    };
}

async function callPost(host, topic, message) {
    try {
        const protocol = dtlsEnabled ? "coaps" : "coap";
        const port = dtlsEnabled ? 5684 : 5683;
        const url = `${protocol}://${host}:${port}/?t=${topic}`;

        if (dtlsEnabled) {
            console.log("Enabling DTLS...");
            const boostrapUrl = `coap://${host}:5683/bootstrap`;
            const { clientIdentity, preSharedKey } = await coapOnboard(boostrapUrl);
            enableDtls(url, clientIdentity, preSharedKey);
            console.log("DTLS enabled");
        }

        await tryToConnectToCoapServer(url);
        await sendCoapMessage(url, message);
        console.log("Coap message sent");
    } catch (error) {
        console.error("Coap exception", error);
        throw error;
    } finally {
        coap.reset();
    }
}

(async () => {
    const message = {
        timestamp: new Date().getTime(),
        description: "Example message",
    };

    const host = "coap.os.1nce.com";
    const topic = "sometesttopic"

    await callPost(host, topic, JSON.stringify(message));
})();
```

Enable or disable the CoAP DTLS connection on line 4. By default, the script uses DTLS.

## Retrieving Device Location (GET)

The following script retrieves the device location via a CoAP GET request to `/location`.

### Plain CoAP

```javascript
const { CoapClient } = require("node-coap-client");

async function getLocation() {
    try {
        const url = "coap://coap.os.1nce.com:5683/location";

        const options = {
            keepAlive: false,
            confirmable: true,
            retransmit: true,
        };

        console.log(`Requesting location from ${url}`);
        const result = await CoapClient.request(url, "get", undefined, options);
        const code = result.code.toString();

        if (code === "4.01") {
            console.error("Unauthorized: Device not found by source IP");
            return;
        }
        if (code === "4.04") {
            console.error("Not Found: No location data available for this device");
            return;
        }
        if (code === "4.05") {
            console.error("Method Not Allowed: Only GET requests are supported on /location");
            return;
        }
        if (code === "5.02") {
            console.error("Bad Gateway: Upstream location service error");
            return;
        }
        if (code === "5.04") {
            console.error("Gateway Timeout: Upstream location service did not respond");
            return;
        }

        if (code !== "2.05") {
            console.error(`Unexpected response code: ${code}`);
            return;
        }

        const payload = result.payload.toString();
        console.log(`Response payload:\n${payload}`);

        // Parse CSV: split on line-feed to get rows, then split data row on comma
        const rows = payload.split("\n");
        const dataRow = rows[1];
        const [Longitude, Latitude, Source, SampleTime] = dataRow.split(",");

        console.log("===================================");
        console.log("Device Location:");
        console.log(`Longitude: ${Longitude}`);
        console.log(`Latitude: ${Latitude}`);
        console.log(`Source: ${Source}`);
        console.log(`SampleTime: ${SampleTime}`);
        console.log("===================================");
    } catch (error) {
        console.error("CoAP exception", error);
        throw error;
    } finally {
        CoapClient.reset();
    }
}

(async () => {
    await getLocation();
})();
```

### DTLS Variant

This variant first calls `/bootstrap` to obtain PSK credentials, then accesses the location endpoint securely.

```javascript
const { CoapClient } = require("node-coap-client");

async function getLocationWithDtls() {
    try {
        const host = "coap.os.1nce.com";

        // Step 1: Call /bootstrap to obtain PSK credentials
        const bootstrapUrl = `coap://${host}:5683/bootstrap`;
        console.log(`Calling CoAP bootstrap endpoint ${bootstrapUrl}`);

        const bootstrapResult = await CoapClient.request(bootstrapUrl, "get", undefined, {
            keepAlive: false,
            confirmable: true,
            retransmit: true,
        });

        if (bootstrapResult.code.toString() !== "2.05") {
            throw new Error(`Bootstrap failed. Code: ${bootstrapResult.code.toString()}`);
        }

        const bootstrapPayload = bootstrapResult.payload.toString();
        const [clientIdentity, preSharedKey] = bootstrapPayload.split(",");

        console.log("===================================");
        console.log("DTLS details:");
        console.log(`Client Identity: ${clientIdentity}`);
        console.log(`Pre-shared key: ${preSharedKey}`);
        console.log("===================================");

        // Step 2: Set DTLS security params and request location
        const locationUrl = `coaps://${host}:5684/location`;

        CoapClient.setSecurityParams(locationUrl, {
            psk: {
                [clientIdentity]: preSharedKey,
            },
        });

        const options = {
            keepAlive: false,
            confirmable: true,
            retransmit: true,
        };

        console.log(`Requesting location from ${locationUrl}`);
        const result = await CoapClient.request(locationUrl, "get", undefined, options);
        const code = result.code.toString();

        if (code === "4.01") {
            console.error("Unauthorized: Device not found by source IP");
            return;
        }
        if (code === "4.04") {
            console.error("Not Found: No location data available for this device");
            return;
        }
        if (code === "4.05") {
            console.error("Method Not Allowed: Only GET requests are supported on /location");
            return;
        }
        if (code === "5.02") {
            console.error("Bad Gateway: Upstream location service error");
            return;
        }
        if (code === "5.04") {
            console.error("Gateway Timeout: Upstream location service did not respond");
            return;
        }

        if (code !== "2.05") {
            console.error(`Unexpected response code: ${code}`);
            return;
        }

        const payload = result.payload.toString();
        console.log(`Response payload:\n${payload}`);

        // Parse CSV: split on line-feed to get rows, then split data row on comma
        const rows = payload.split("\n");
        const dataRow = rows[1];
        const [Longitude, Latitude, Source, SampleTime] = dataRow.split(",");

        console.log("===================================");
        console.log("Device Location:");
        console.log(`Longitude: ${Longitude}`);
        console.log(`Latitude: ${Latitude}`);
        console.log(`Source: ${Source}`);
        console.log(`SampleTime: ${SampleTime}`);
        console.log("===================================");
    } catch (error) {
        console.error("CoAP exception", error);
        throw error;
    } finally {
        CoapClient.reset();
    }
}

(async () => {
    await getLocationWithDtls();
})();
```
