main.cpp
#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 =====
WiFiUDP udp;
Coap coap(udp, 256);
 
// ===== On-board NeoPixel (GPIO 3) =====
constexpr uint8_t kNeoPixelPin = 3;
constexpr uint8_t kNeoPixelCount = 1;
constexpr uint8_t kNeoPixelBrightness = 128; // 50% to limit power draw
 
Adafruit_NeoPixel g_pixel(kNeoPixelCount, kNeoPixelPin, NEO_GRB + NEO_KHZ800);
bool g_pixelReady = false;
 
// ===== Simple LED state =====
static bool g_ledOn = false;
 
void applyLedState() {
  if (!g_pixelReady) {
    return;
  }
  if (g_ledOn) {
    g_pixel.setPixelColor(0, g_pixel.Color(255, 255, 255));
  } else {
    g_pixel.setPixelColor(0, 0, 0, 0);
  }
  g_pixel.show();
}
 
// ----- helper: send text/plain 2.05 Content -----
static void coapSendText(IPAddress ip, int port, const CoapPacket& req,
                         const char* text) {
  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_CONTENT,      // 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) -----
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") -----
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) {
    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
    const char* state = g_ledOn ? "on" : "off";
    coap.sendResponse(
      ip, port, packet.messageid,
      state, strlen(state),
      COAP_CHANGED,      // 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_METHOD_NOT_ALLOWD,
    COAP_TEXT_PLAIN,
    packet.token, packet.tokenlen
  );
}
 
// ----- /echo (POST/PUT echoes payload; GET returns hint) -----
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_CONTENT,      // 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_CONTENT,
    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();
}
iothings/laboratoare/2025_code/lab4_2.txt · Last modified: 2025/10/21 16:59 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