Differences

This shows you the differences between two versions of the page.

Link to this comparison view

iothings:laboratoare:2025:lab4 [2025/10/14 14:34]
dan.tudose [CoAP Server]
iothings:laboratoare:2025:lab4 [2025/10/28 11:29] (current)
dan.tudose [CoAP Server]
Line 80: Line 80:
 On the CoAP side, the library handles all the protocol details—message type, message ID, token management, options, and parsing—so your sketch only deals with high-level actions. You issue a client request with coap.get(remoteIP,​ 5683, ""​),​ and when the server replies, the callback receives a parsed CoapPacket. The code prints the CoAP code (e.g., 2.xx success), basic header info, and the payload as text.  On the CoAP side, the library handles all the protocol details—message type, message ID, token management, options, and parsing—so your sketch only deals with high-level actions. You issue a client request with coap.get(remoteIP,​ 5683, ""​),​ and when the server replies, the callback receives a parsed CoapPacket. The code prints the CoAP code (e.g., 2.xx success), basic header info, and the payload as text. 
  
- +[[iothings:laboratoare:2025_code:​lab4_1|Click here to get the code example]]
-<code C main.cpp>​ +
-#include <​Arduino.h>​ +
-#include <​WiFi.h>​ +
-#include <​WiFiUdp.h>​ +
-#include <​coap-simple.h> ​  // hirotakaster/​CoAP simple library +
- +
-// ===== Wi-Fi creds ===== +
-const char* WIFI_SSID = "​UPB-Guest";​ +
-const char* WIFI_PASS = "";​ +
- +
-// ===== CoAP server (Californium demo) ===== +
-const char* COAP_HOST = "​californium.eclipseprojects.io";​ +
-const uint16_t COAP_PORT = 5683;   // RFC 7252 default port +
- +
-// UDP + CoAP objects +
-WiFiUDP udp; +
-Coap coap(udp);​ +
- +
-// ----- Response callback: prints payload as text ----- +
-void onCoapResponse(CoapPacket &​packet,​ IPAddress ip, int port) { +
-  // Copy payload into a printable buffer +
-  const size_t n = packet.payloadlen;​ +
-  String from = ip.toString() + ":"​ + String(port);​ +
-  Serial.printf("​[CoAP] Response from %s  code=%u (0x%02X) ​ len=%u\n",​ +
-                from.c_str(),​ (packet.code >> 5), packet.code,​ (unsigned)n);​ +
- +
-  if (n > 0) { +
-    // Make it printable; not all payloads are ASCII +
-    size_t m = n; +
-    if (m > 1023) m = 1023;     // clamp for serial +
-    char buf[1024]; +
-    memcpy(buf, packet.payload,​ m); +
-    buf[m] = '​\0';​ +
-    Serial.println(F("​[CoAP Payload]"​));​ +
-    Serial.println(buf);​ +
-  } +
-+
- +
-// Re-resolves hostname and sends GET to "/"​ +
-bool coapGetRoot() { +
-  IPAddress remote; +
-  if (!WiFi.hostByName(COAP_HOST,​ remote)) { +
-    Serial.println(F("​[CoAP] DNS failed"​));​ +
-    return false; +
-  } +
-  Serial.printf("​[CoAP] GET coap://%s:%u/​\n",​ COAP_HOST, COAP_PORT);​ +
-  // Path is ""​ for "/",​ per library examples +
-  int msgid = coap.get(remote, COAP_PORT, ""​);​ +
-  (void)msgid;​ // not used further in this demo +
-  return true; +
-+
- +
-unsigned long lastGetMs = 0; +
-const unsigned long GET_PERIOD_MS = 10000; +
- +
-void setup() { +
-  Serial.begin(115200);​ +
-  delay(200);​ +
-  Serial.println(F("​\n== CoAP client (Californium demo) =="​));​ +
- +
-  // Wi-Fi +
-  WiFi.mode(WIFI_STA);​ +
-  WiFi.begin(WIFI_SSID,​ WIFI_PASS);​ +
-  Serial.print(F("​Connecting"​));​ +
-  while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print('​.'​);​ } +
-  Serial.println();​ +
-  Serial.print(F("​Wi-Fi OK. IP: ")); Serial.println(WiFi.localIP());​ +
- +
-  // Bind UDP so we can receive responses (use standard CoAP port or 0 for ephemeral) +
-  udp.begin(5683);​ +
- +
-  // Register response handler and start CoAP +
-  coap.response(onCoapResponse);​ +
-  coap.start();​ +
- +
-  // First GET right away +
-  coapGetRoot();​ +
-  lastGetMs = millis(); +
-+
- +
-void loop() { +
-  // Let the library process incoming UDP (and fire onCoapResponse) +
-  coap.loop();​ +
- +
-  // Periodic GET +
-  unsigned long now = millis(); +
-  if (now - lastGetMs >= GET_PERIOD_MS) { +
-    lastGetMs = now; +
-    coapGetRoot();​ +
-  } +
-+
- +
-</code>+
  
 After building, you should get a similar print-out in the console: After building, you should get a similar print-out in the console:
Line 195: Line 102:
 **Debian/​Ubuntu** **Debian/​Ubuntu**
  
-   sudo apt update\\ +   sudo apt update 
-   sudo apt install -y libcoap2-bin\\+   sudo apt install -y libcoap2-bin
    # binaries: coap-client,​ coap-server    # binaries: coap-client,​ coap-server
  
 **macOS** **macOS**
  
-   # needs Homebrew: https://​brew.sh\\ +   # needs Homebrew: https://​brew.sh 
-   brew update\\ +   brew update 
-   brew install libcoap\\+   brew install libcoap
    # binaries: coap-client,​ coap-server    # binaries: coap-client,​ coap-server
  
 **Windows** **Windows**
  
-   # Install WSL (once)\\ +   # Install WSL (once) 
-   wsl --install\\ +   wsl --install 
-   # Open Ubuntu in WSL, then:\\ +   # Open Ubuntu in WSL, then: 
-   sudo apt update\\ +   sudo apt update 
-   sudo apt install -y libcoap2-bin\\+   sudo apt install -y libcoap2-bin
  
 </​note>​ </​note>​
  
-<code C main.cpp> +[[iothings:​laboratoare:​2025_code:​lab4_2|Click here to get the code example.]]
-#include <​Arduino.h>​ +
-#include <​WiFi.h>​ +
-#include <​WiFiUdp.h>​ +
-#include <​Adafruit_NeoPixel.h>​ +
-#include <​coap-simple.h> ​  // hirotakaster CoAP simple library+
  
-// ===== Wi-Fi creds ===== 
-const char* WIFI_SSID = "​UPB-Guest";​ 
-const char* WIFI_PASS = "";​ 
  
-// ===== UDP + CoAP objects ===== +Test it from your computer with the following commands, where esp-ip is the IP the node prints after connecting in the serial terminal:
-WiFiUDP udp; +
-Coap coap(udp);+
  
-// ===== On-board NeoPixel (GPIO 3) ===== +<​code>​ 
-constexpr uint8_t kNeoPixelPin = 3; +# discovery 
-constexpr uint8_t kNeoPixelCount = 1; +coap-client -v9 -m get -A 40 coap://<esp-ip>/.well-known/core
-constexpr uint8_t kNeoPixelBrightness = 128; // 50% to limit power draw+
  
-Adafruit_NeoPixel g_pixel(kNeoPixelCount,​ kNeoPixelPin,​ NEO_GRB + NEO_KHZ800);​ +# other resources 
-bool g_pixelReady = false;+coap-client -v9 -m get coap://<​esp-ip>/​sys/​uptime 
 +coap-client -v9 -m get coap://<​esp-ip>/​net/​rssi 
 +coap-client -v9 -m get coap://<​esp-ip>/​led 
 +coap-client -v9 -m put -e "​on" ​ coap://<​esp-ip>/​led 
 +coap-client -v9 -m put -e "​off"​ coap://<​esp-ip>/​led 
 +coap-client -v9 -m post -e "​hello"​ coap://<​esp-ip>/​echo
  
-// ===== Simple LED state ===== +</code>
-static bool g_ledOn = false;+
  
-void applyLedState() { +<​note>​**Assignment 1:** 
-  if (!g_pixelReady) { +Add BME680 functionality to this code in order to query sensor values through CoAPThey should be available at /​sensors/​temperature/​sensors/​humidity/​sensors/​pressure 
-    return; +</​note>​
-  } +
-  if (g_ledOn) { +
-    g_pixel.setPixelColor(0g_pixel.Color(255255, 255)); +
-  } else { +
-    g_pixel.setPixelColor(0,​ 0, 0, 0); +
-  } +
-  g_pixel.show();​ +
-}+
  
-// ----- helpersend text/plain 2.05 Content ----- +<​note>​**Assignment 2:** 
-static void coapSendText(IPAddress ip, int port, const CoapPacket&​ req, +Build a web page that acts as a GUI for your coap-client queries ​(e.gyou can do discoveryget and put/post from the pageYou will probably need a proxy to translate ​coap datagrams to WS or HTTP
-                         const chartext) { +</note>
-  ​Serial.printf("​[CoAP] Replying to %s:%d mid=%u code=%u tokensz=%u\n",​ +
-                ip.toString().c_str()port, req.messageid, req.code, req.tokenlen);​ +
-  ​coap.sendResponse( +
-    ip, port, req.messageid,​ +
-    text, strlen(text),​ +
-    COAP_RESPONSE_CODE(205), ​     ​// 2.05 Content +
-    COAP_TEXT_PLAIN,​ +
-    req.token, req.tokenlen +
-  ); +
-}+
  
-// ----- /sys/uptime (GET) ----- 
-void h_sys_uptime(CoapPacket &​packet,​ IPAddress ip, int port) { 
-  unsigned long secs = millis() / 1000UL; 
-  char buf[32]; 
-  snprintf(buf,​ sizeof(buf),​ "​%lu",​ (unsigned long)secs); 
-  coapSendText(ip,​ port, packet, buf); 
-} 
  
-// ----- /net/rssi (GET) ----- +<​hidden>​
-void h_net_rssi(CoapPacket &​packet,​ IPAddress ip, int port) { +
-  long rssi = WiFi.RSSI();​ +
-  char buf[16]; +
-  snprintf(buf,​ sizeof(buf),​ "​%ld",​ rssi); +
-  coapSendText(ip,​ port, packet, buf); +
-}+
  
-// ----- /led (GET state, PUT/POST "​on"​ or "​off"​) ​----- +For assignment 2, run the above ESP32 code example and get the board IP. Run the python proxy script below (edit it in advance and specify the ESP IP COAP_HOST).
-void h_led(CoapPacket &​packet,​ IPAddress ip, int port+
-  if (packet.code == COAP_GET) { +
-    coapSendText(ip,​ port, packet, g_ledOn ? "​on"​ : "​off"​);​ +
-    return; +
-  }+
  
-  if (packet.code == COAP_PUT || packet.code == COAP_POST) { +[[iothings:​laboratoare:​2025_code:​lab4_proxy|Python proxy script]]
-    String body; +
-    body.reserve(packet.payloadlen + 1); +
-    for (size_t i = 0; i < packet.payloadlen;​ ++i) body += (char)packet.payload[i]+
-    body.trim();​ +
-    if (body.equalsIgnoreCase("​on"​)) ​ g_ledOn = true; +
-    if (body.equalsIgnoreCase("​off"​)) g_ledOn = false;+
  
-    applyLedState();​ 
  
-    ​// Acknowledge change (2.04 Changed) ​and return new state +Then open the webpage [[https://dantudose.github.io/​labs/​lab4_1.html|here]] ​and edit the following fields: ​ 
-    const char* state = g_ledOn ? "​on" ​"​off";​ +Proxy base URL:   http://localhost:​8080 
-    coap.sendResponse( +CoAP host:        ESP32_IP - from serial terminal
-      ip, port, packet.messageid,​ +
-      state, strlen(state),​ +
-      COAP_RESPONSE_CODE(204), ​     ​// 2.04 Changed +
-      ​COAP_TEXT_PLAIN,​ +
-      packet.token,​ packet.tokenlen +
-    ); +
-    return; +
-  }+
  
-  // Method not allowed 
-  coap.sendResponse( 
-    ip, port, packet.messageid,​ 
-    "​Method Not Allowed",​ 18, 
-    COAP_RESPONSE_CODE(405),​ 
-    COAP_TEXT_PLAIN,​ 
-    packet.token,​ packet.tokenlen 
-  ); 
-} 
  
-// ----- /echo (POST/PUT echoes payload; GET returns hint) ----- +</hidden>
-void h_echo(CoapPacket &​packet,​ IPAddress ip, int port) { +
-  if (packet.payloadlen == 0 || packet.code == COAP_GET) { +
-    const char* hint = "​POST/​PUT a payload and I'll echo it.";​ +
-    coapSendText(ip,​ port, packet, hint); +
-    return; +
-  } +
-  coap.sendResponse( +
-    ip, port, packet.messageid,​ +
-    (const char*)packet.payload,​ packet.payloadlen,​ +
-    COAP_RESPONSE_CODE(205), ​     // 2.05 Content +
-    COAP_TEXT_PLAIN,​ +
-    packet.token,​ packet.tokenlen +
-  ); +
-+
- +
-// ----- /​.well-known/​core (RFC 6690 CoRE Link Format) ----- +
-void h_wkc(CoapPacket &​packet,​ IPAddress ip, int port) { +
-  Serial.printf("​[CoAP] Discovery hit from %s:%d type=%u code=%u accept=%s\n",​ +
-                ip.toString().c_str(),​ +
-                port, +
-                packet.type,​ +
-                packet.code,​ +
-                packet.optionnum ? "​yes"​ : "​no"​);​ +
-  // Advertise resources and basic attributes +
-  const char* linkfmt = +
-    "</​sys/​uptime>;​rt=\"​sys.uptime\";​if=\"​core.a\";​ct=0,"​ +
-    "</​net/​rssi>;​rt=\"​net.rssi\";​if=\"​core.a\";​ct=0,"​ +
-    "</​led>;​rt=\"​dev.led\";​if=\"​core.a\";​ct=0,"​ +
-    "</​echo>;​rt=\"​util.echo\";​if=\"​core.p\";​ct=0";​ +
- +
-  coap.sendResponse( +
-    ip, port, packet.messageid,​ +
-    linkfmt, strlen(linkfmt),​ +
-    COAP_RESPONSE_CODE(205),​ +
-    COAP_APPLICATION_LINK_FORMAT,​ // ct=40 +
-    packet.token,​ packet.tokenlen +
-  ); +
-+
- +
-void setup() { +
-  Serial.begin(115200);​ +
-  delay(200);​ +
-  Serial.println("​\n== CoAP RESTful mapping & discovery (server-only) =="​);​ +
- +
-  // Wi-Fi +
-  WiFi.mode(WIFI_STA);​ +
-  WiFi.begin(WIFI_SSID,​ WIFI_PASS);​ +
-  Serial.print("​Connecting"​);​ +
-  while (WiFi.status() != WL_CONNECTED) { delay(300); Serial.print("​."​);​ } +
-  Serial.println();​ +
-  Serial.print("​Wi-Fi OK. IP: "); Serial.println(WiFi.localIP());​ +
-  Serial.printf("​Listening for CoAP on udp/​%d\n",​ COAP_DEFAULT_PORT);​ +
- +
-  g_pixel.begin();​ +
-  g_pixel.setBrightness(kNeoPixelBrightness);​ +
-  g_pixel.clear();​ +
-  g_pixel.show();​ +
-  g_pixelReady = true; +
-  applyLedState();​ +
- +
-  // Start CoAP server on udp/5683 +
-  udp.begin(5683);​ +
- +
-  // Register resources +
-  coap.server(h_sys_uptime,​ "​sys/​uptime"​);​ +
-  coap.server(h_net_rssi, ​  "​net/​rssi"​);​ +
-  coap.server(h_led, ​       "​led"​);​ +
-  coap.server(h_echo, ​      "​echo"​);​ +
-  coap.server(h_wkc, ​       "​.well-known/​core"​);​ // discovery +
- +
-  // Start CoAP stack +
-  coap.start();​ +
-+
- +
-void loop() { +
-  // Process incoming CoAP requests +
-  coap.loop();​ +
-+
-</​code>​ +
- +
-Test it from your computer with the following commands, where esp-ip is the IP the node prints after connecting in the serial terminal: +
- +
-<​code>​ +
-# discovery +
-coap-client -v9 -m get -A 40 coap://<​esp-ip>/​.well-known/​core +
- +
-# other resources +
-coap-client -m get coap://<​esp-ip>/​sys/​uptime +
-coap-client -m get coap://<​esp-ip>/​net/​rssi +
-coap-client -m get coap://<​esp-ip>/​led +
-coap-client -m put -e "​on" ​ coap://<​esp-ip>/​led +
-coap-client -m put -e "​off"​ coap://<​esp-ip>/​led +
-coap-client -m post -e "​hello"​ coap://<​esp-ip>/​echo +
- +
-</code>+
iothings/laboratoare/2025/lab4.1760441670.txt.gz · Last modified: 2025/10/14 14:34 by dan.tudose
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0