Wizarduino로 CoAP 통신하기

1. CoAP란?

CoAP_main


이번 예제에서는 Wizarduino를 이용하여 CoAP통신을 하려고 합니다.

arduino의 간단한 예제를 이용하여 구현방법을 소개하겠습니다.

먼저, CoAP란 Constrained Application Protocol의 약자로 저사양 모듈을 위한 application 프로토콜 입니다.

다시 말해 HTTP를 사용하고 싶으나, 리소스가 제한된 WPAN 기기를 위한 lightweight 버전이라고 볼 수 있습니다.

저전력을 지향하고, 센서 데이터 전달이 주된 목적이며, 비동기적인 요청/응답 디자인 구조를 지녔습니다.

method는 GET, POST, PUT, DELETE 총 네가지가 있습니다.

HTTP와 비교하면 아래와 같은 layer를 가집니다.

application CoAP HTTP
Session DTLS SSL/TLS
Transport UDP TCP
Network 6LoWPAN(IPv6) IP
Data Link 802.15.4 MAC 802.3 MAC
Physical 802.15.4Phy 802.3 Phy

2. Setup

Server와 Client 구성을 위해 두개의 Wizarduino를 사용하였습니다.


아두이노 예제를 수정하여서 Client에서 조도센서 데이터값을 읽어 light ON/OFF를 판단하여 서버로 전송하면, 서버측에서 LED를 ON/OFF 해주도록 할것입니다.


우선, Wizarduino는 M0기반이기 때문에 먼저 M0보드를 따로 추가해줘야 합니다.


Add_M0board


보드매니저에서 M0로 검색하여 설치하면 그림과 같이 M0보드를 선택할 수 있게 됩니다.

다음으로는 library를 추가해야합니다.


W5500기반이기때문에 Ethernet library와는 호환이 되지않아 Ethernet2 library를 따로 추가해줘야하고, CoAP library를 설치해 주어야합니다.


Add_library


board 추가와 마찬가지로 Ethernet2, CoAP로 검색하여 가장 상단에 있는 library를 설치해주면 됩니다.


3. CODE – Server

위에서 CoAP Simple library를 설치해주었다면 파일-예제에서도 CoAP Simple library를 볼 수 있을겁니다.


coapserver를 선택해주세요

(1) 먼저 include파일을 바꿔주어야 합니다.

Ethernet2 library를 설치해준것과 같은 이유로 빨간 박스부분에 2를 추가해줍니다. (Ethernet2.h, EthernetUdp2.h)


CoAP_header

(2) Serial 부분을 모두 SerialUSB로 수정해주세요.

(3) 아래 그림 부분에 mac주소도 알맞게 수정해주세요.

CoAP_mac


이 예제에서는 IP를 할당받아서 사용하고있습니다. 고정 IP를 사용하고싶은 분들은 수정해주세요.

(4) LED PIN 설정.

저는 Digital 9번 PIN에 LED가 연결되어있습니다. 다른 pin에 연결하실 분들은 40,43번째 줄을 수정해주세요 (Setup에서 digital mode 설정한 부분도 수정해 주세요)


CoAP_server_led

(5) 이 예제에서는 client에서 보내는 데이터를 server가 수신하기만하면 됩니다.

따라서 server에서는 request를 보낼 필요가없으므로 아래부분을 주석처리해주세요.


CoAP_server_loop

(6) code

#include <SPI.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet2.h>
#include <EthernetUdp2.h>
#include <coap.h>

byte mac[] = { 0x00, 0x08, 0xdc, 0x50, 0xf4, 0xe7 };

// CoAP client response callback
void callback_response(CoapPacket &packet, IPAddress ip, int port);

// CoAP server endpoint url callback
void callback_light(CoapPacket &packet, IPAddress ip, int port);

// UDP and CoAP class
EthernetUDP Udp;
Coap coap(Udp);

// LED STATE
bool LEDSTATE;

// CoAP server endpoint URL
void callback_light(CoapPacket &packet, IPAddress ip, int port) {
  SerialUSB.println("[Light] ON/OFF");

  // send response
  char p[packet.payloadlen + 1];
  memcpy(p, packet.payload, packet.payloadlen);
  p[packet.payloadlen] = NULL;

  String message(p);

  if (message.equals("0")){
    SerialUSB.println("false");
    LEDSTATE = false;
  }
  else if(message.equals("1")) {
    SerialUSB.println("true");
    LEDSTATE = true;
  }

  if (LEDSTATE) {
    digitalWrite(9, HIGH) ; 
    coap.sendResponse(ip, port, packet.messageid, "1");
  } else { 
    digitalWrite(9, LOW) ; 
    coap.sendResponse(ip, port, packet.messageid, "0");
  }
}

// CoAP client response callback
void callback_response(CoapPacket &packet, IPAddress ip, int port) {
  SerialUSB.println("[Coap Response got]");

  char p[packet.payloadlen + 1];
  memcpy(p, packet.payload, packet.payloadlen);
  p[packet.payloadlen] = NULL;

  SerialUSB.println(p);
}

void setup() {
  SerialUSB.begin(9600);

  Ethernet.begin(mac);
  SerialUSB.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    SerialUSB.print(Ethernet.localIP()[thisByte], DEC);
    SerialUSB.print(".");
  }
  SerialUSB.println();

  // LED State
  pinMode(9, OUTPUT);
  digitalWrite(9, HIGH);
  LEDSTATE = true;

  // add server url endpoints.
  // can add multiple endpoint urls.
  // exp) coap.server(callback_switch, "switch");
  //      coap.server(callback_env, "env/temp");
  //      coap.server(callback_env, "env/humidity");
  SerialUSB.println("Setup Callback Light");
  coap.server(callback_light, "light");

  // client response callback.
  // this endpoint is single callback.
  SerialUSB.println("Setup Response Callback");
  coap.response(callback_response);

  // start coap server/client
  coap.start();
}

void loop() {
  // send GET or PUT coap request to CoAP server.
  // To test, use libcoap, microcoap server...etc
  // int msgid = coap.put(IPAddress(10, 0, 0, 1), 5683, "light", "1");
 // SerialUSB.println("Send Request");
 // int msgid = coap.get(IPAddress(192, 168, 0, 67), 5683, "time");
  delay(1000);
  coap.loop();
}
/*
if you change LED, req/res test with coap-client(libcoap), run following.
coap-client -m get coap://(arduino ip addr)/light
coap-client -e "1" -m put coap://(arduino ip addr)/light
coap-client -e "0" -m put coap://(arduino ip addr)/light
*/

CODE – Client

client에서는 coaptest 예제를 선택해서 열어주세요

(1) Server에서와 마찬가지로 SerialUSB로변경, include파일 수정, mac주소변경(ip주소변경 선택사항)을 해줍니다.

(2) 조도센서 데이터를 읽어서 request를 보내주어야 합니다. 아래와 같이 수정해주세요.

server ip에 맞게 설정해주고, 조도센서가 연결되어있는 핀값을 읽어옵니다.

(저는 A1에 조도센서가 연결되어있습니다.)


조도센서값이 250이상일 경우에 LED를 ON하도록 데이터를 보내주었습니다.


CoAP_client_loop

(3) code

#include <SPI.h>
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet2.h>
#include <EthernetUdp2.h>
#include <coap.h>

byte mac[] = { 0x00, 0x08, 0xdc, 0x50, 0xf4, 0xe9 };

// CoAP client response callback
void callback_response(CoapPacket &packet, IPAddress ip, int port);

// UDP and CoAP class
EthernetUDP Udp;
Coap coap(Udp);

// CoAP client response callback
void callback_response(CoapPacket &packet, IPAddress ip, int port) {
  SerialUSB.println("[Coap Response got]");

  char p[packet.payloadlen + 1];
  memcpy(p, packet.payload, packet.payloadlen);
  p[packet.payloadlen] = NULL;

  SerialUSB.println(p);
}

void setup() {
  SerialUSB.begin(9600);

  Ethernet.begin(mac);
  SerialUSB.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    SerialUSB.print(Ethernet.localIP()[thisByte], DEC);
    SerialUSB.print(".");
  }
  SerialUSB.println();


  // client response callback.
  // this endpoint is single callback.
  SerialUSB.println("Setup Response Callback");
  coap.response(callback_response);

  // start coap server/client
  coap.start();
}

void loop() {
  // send GET or PUT coap request to CoAP server.
  // To test, use libcoap, microcoap server...etc
  int msgid;
  int cdsVal=analogRead(A1);
  SerialUSB.println(cdsVal);
  if(cdsVal>=250) {
    msgid = coap.put(IPAddress(192, 168, 0, 61), 5683, "light", "1");
  }
  else {
    msgid = coap.put(IPAddress(192, 168, 0, 61), 5683, "light", "0");
  }

  SerialUSB.println("Send Request");
  //int msgid = coap.get(IPAddress(XXX, XXX, XXX, XXX), 5683, "time");

  delay(1000);
  coap.loop();
}

Result

조도센서를 가렸다가 뗐을때의 결과입니다.


CoAP_Serial


응용해보세요~~~!