ESP32 Communication Protocol – CoAP

Constrained Application Protocol (CoAP) adalah client-server protocol dimana servers akan expose resources ke network dan clients mengirim HTTP requests untuk get atau set state dari resources.

CoAP didesain khusus untuk resource-limited low-power IoT devices sebagai Representational State Transfer (REST) communication protocol dengan overheads yang rendah.

CoAP awalnya berjalan diatas UDP, namun dapat berjalan diatas transport protocols lainnya.

Sebagai contoh, ketika CoAP di port ke proprietary wireless network, node dapat berkomunikasi dengan mudah dengan external IP network jika digunakan gateway yang akan translates messages pada level transport.

Untuk security, dapat digunakan DTLS.

Untuk keperluan modul ini, kita perlu install CoAP client. SIlakan download di https://libcoap.net/install.html

Untuk persiapan project, sama dengan yang telah kita bahas pada modul MQTT. Kita tidak akan bahas ulang. Kita akan langsung bahas coding aplikasi.

Code

Buka src/main.c masukan code dibawah:

//import library dan init variable
#include <string.h>
#include <stdint.h>
#include <sys/socket.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"

#include "esp_log.h"
#include "esp_event.h"

#include "app_temp.h"
#include "app_wifi.h"

#include "coap.h"

const static char *TAG = "app";

static int temperature, humidity;

// fungsi handle sensor get
static void
handle_sensor_get(coap_context_t *ctx,
                  coap_resource_t *resource,
                  coap_session_t *session,
                  coap_pdu_t *request,
                  coap_binary_t *token,
                  coap_string_t *query,
                  coap_pdu_t *response)
{
    char buff[100];
    memset(buff, 0, sizeof(buff));
    if (!strcmp("temperature", (const char *)(resource->uri_path->s)))
    {
        sprintf(buff, "{\"temperature\": %d}", temperature);
    }
    else
    {
        sprintf(buff, "{\"humidity\": %d}", humidity);
    }
    coap_add_data_blocked_response(resource, session, request, response, token,
                                   COAP_MEDIATYPE_APPLICATION_JSON, 0,
                                   strlen(buff), (const uint8_t *)buff);
}

// fungsi sensor server
static void sensor_server(void *p)
{
    coap_context_t *ctx = NULL;
    coap_address_t serv_addr;
    coap_resource_t *temp_resource = NULL;
    coap_resource_t *hum_resource = NULL;

    coap_set_log_level(LOG_DEBUG);

    while (1)
    {
        coap_address_init(&serv_addr);
        serv_addr.addr.sin.sin_family = AF_INET;
        serv_addr.addr.sin.sin_addr.s_addr = INADDR_ANY;
        serv_addr.addr.sin.sin_port = htons(COAP_DEFAULT_PORT);

        ctx = coap_new_context(NULL);
        coap_new_endpoint(ctx, &serv_addr, COAP_PROTO_UDP);

        temp_resource = coap_resource_init(coap_make_str_const("temperature"), 0);
        coap_register_handler(temp_resource, COAP_REQUEST_GET, handle_sensor_get);
        coap_add_resource(ctx, temp_resource);

        hum_resource = coap_resource_init(coap_make_str_const("humidity"), 0);
        coap_register_handler(hum_resource, COAP_REQUEST_GET, handle_sensor_get);
        coap_add_resource(ctx, hum_resource);

        while (1)
        {
            int result = coap_run_once(ctx, 2000);
            if (result < 0)
            {
                break;
            }
        }
        coap_free_context(ctx);
        coap_cleanup();
    }

    vTaskDelete(NULL);
}

// fungsi update reading
static void update_reading(int temp, int hum)
{
    temperature = temp;
    humidity = hum;
}

// fungsi handle wifi connect
static void handle_wifi_connect(void)
{
    xTaskCreate(sensor_server, "coap", 8 * 1024, NULL, 5, NULL);
    apptemp_init(update_reading);
}

// fungsi handle wifi failed
static void handle_wifi_failed(void)
{
    ESP_LOGE(TAG, "wifi failed");
}

// main function
void app_main()
{
    connect_wifi_params_t cbs = {
        .on_connected = handle_wifi_connect,
        .on_failed = handle_wifi_failed};
    appwifi_connect(cbs);
}

Penjelasan Code

Bagian Import dan Variable Init

Untuk menggunakan coap, kita import header files coap.h. Kita juga definsikan dua global variables untuk menyimpan data temperature dan humidity.

Bagian Main Function

Pertama kita connect ke local Wi-Fi dengan menjalakan appwifi_connect.

handle_wifi_connect adalah callback function yang dijalankan ketika aplikasi terhubung dengan local Wi-Fi. Didalam fungsi ini, kita jalankan FreeRTOS task untuk CoAP server dan inisialisasi DHT11 sensor dengan passing update_reading function sebagai the callback.

Bagian Fungsi Sensor Server

Pertama kita definisikan local variables ctx yang akan menyimpan informasi CoAP context. Kita deklarasikan server address variable dan pointers untuk dua CoAP resources yang akan di expose pada CoAP server.

Kemudian kita start server. Pada while loop akan dilakukan restart bila terjadi failure. Kita init server address structure dan membuat context baru. Kemudian passing sebagai parameter ke fungsi coap_new_endpoint, untuk membuat endpoint bagi client untuk connect.

Endpoint berjalan diatas UDP dan defaul port untuk COAP adalah 5683.

Selanjutnya kita buat resource.

Resource pertama adalah untuk temperature. Setelah inisialisasi, kita register handler untuk COAP_REQUEST_GET requests. Kemudian kita tambahkan temperature resource ke CoAP context menggunakan perintah coap_add_resource. Lakukan hal yang sama untuk humidity resource.

Selanjutnya adalah message processing.

while loop kedua untuk melakukan message processing. coap_run_once menunggu request baru. Jika error terjadi, inner loop breaks, bersihkan CoAP context dan resource, dan instance baru akan dibuat di luar loop.

Bagian Handler Sensor Get

Pada fungsi handle_sensor_get, kita periksa resource yang di query dan buat JSON data. Update response dengan JSON data dengan perintah calling coap_add_data_blocked_response.

Compile, Upload dan Test

Pada platformIO CLI, jalankan perintah dibawah:

(penv) $ pio run -t upload 
(penv) $ pio device monitor

Ketika aplikasi berjalan, ESP32 akan connect ke local Wi-Fi dan menjalankan CoAP
server dengan resource temperature dan humidity. Alamat IP dari perangkat akan ditampilkan dalam serial monitor.

Gunakan CoAP client (pada tutorial digunakan https://libcoap.net/).

Buka command line baru dan kirim GET request ke temperature resource. Perhatian, gunakan alamat ip dari PC Anda.

$ coap-client -m get coap://192.168.1.85/temperature
{"temperature": 22}

Untuk query humidity gunakan perintah berikut

$ coap-client -m get coap://192.168.1.85/humidity
{"humidity": 52}

Sampai disini kita sudah berhasil mempelajari penggunakan CoAP server. Pada modul selanjutnya kita akan membahas WebSocket.


Sharing is caring:

Leave a Comment