위의 링크에서 라이브러리를 설치한다. 위의 라이브러리가 그나마 비교적 자료도 많고 예시도 많아서 사용하기 좋다.
설치하고 나면 IDE에서 'WebSockets'라는 라이브러리명을 찾아볼 수 있다.
내가 사용한 보드는 ESP32 기반이었기 때문에 예제코드 중 ESP32 > 'WebSocketClientSocketIOack.ino'라는 파일을 변형해서 사용했다.
'WebSocketClinet.ino' 파일은 WebSocket 클라이언트를 사용하는 예제이고, 'WebSocketClientSocketIOack.ino' 파일은 SocketIO 클라이언트를 사용하는 예제로 엄연히 다른 예제이다.
파일을 열면 파일의 이름과 작성된 날짜가 적힌 주석이 보일 것이다.
그 밑에 헤더파일들이 보일 것인데, 그 중 "WiFiMulti.h"는 사용하지 않을 것이기 때문에 주석처리를 하거나 지워준다. WiFiMulti를 이용해 와이파이에 연결하면 에러가 발생하고 연결도 되지 않기 때문에 사용하지 않는다. 마찬가지로, WiFiMulti로 선언된 객체도 지워준다.
socketIOEvent 함수는 socketIO를 통해 메시지를 수신하면 메시지를 처리하는 함수이다. setup() 함수에서 socketIO.onEvent(socketIOEvent)를 통해 이벤트 처리 함수로 등록한다.
매개변수
실제 코드
void socketIOEvent(socketIOmessageType_t type, uint8_t * payload, size_t length) {
switch(type) {
case sIOtype_CONNECT:
USE_SERIAL.printf("[IOc] Connected to url: %s\n", payload);
// join default namespace (no auto join in Socket.IO V3)
socketIO.send(sIOtype_CONNECT, "/");
break;
case sIOtype_DISCONNECT:
USE_SERIAL.printf("[IOc] Disconnected!\n");
break;
case sIOtype_EVENT:
/*{
char * sptr = NULL;
int id = strtol((char *)payload, &sptr, 10);
USE_SERIAL.printf("[IOc] get event: %s id: %d\n", payload, id);
if(id) {
payload = (uint8_t *)sptr;
}
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, payload, length);
if(error) {
USE_SERIAL.print(F("deserializeJson() failed: "));
USE_SERIAL.println(error.c_str());
return;
}
String eventName = doc[0];
USE_SERIAL.printf("[IOc] event name: %s\n", eventName.c_str());
// Message Includes a ID for a ACK (callback)
if(id) {
// creat JSON message for Socket.IO (ack)
DynamicJsonDocument docOut(1024);
JsonArray array = docOut.to<JsonArray>();
// add payload (parameters) for the ack (callback function)
JsonObject param1 = array.createNestedObject();
param1["now"] = millis();
// JSON to String (serializion)
String output;
output += id;
serializeJson(docOut, output);
// Send event
socketIO.send(sIOtype_ACK, output);
}
}*/
break;
case sIOtype_ACK:
USE_SERIAL.printf("[IOc] get ack: %u\n", length);
break;
case sIOtype_ERROR:
USE_SERIAL.printf("[IOc] get error: %u\n", length);
break;
case sIOtype_BINARY_EVENT:
USE_SERIAL.printf("[IOc] get binary: %u\n", length);
break;
case sIOtype_BINARY_ACK:
USE_SERIAL.printf("[IOc] get binary ack: %u\n", length);
break;
}
}
와이파이에는 연결되었는데 sIOtype_DISCONNECT의 내용만 출력되어서 한동안 고생했던 기억이 있다. 이벤트를 수신했을 때 아두이노를 작동시키고자 한다면 sIOtype_EVENT의 내용을 수정해서 사용하면 된다.
기본적인 설정을 하는 함수이다. WiFi 연결과 socketIO 연결도 진행하게 된다.
따로 사용하고 싶은 하드웨어나 장치가 있으면 일반적인 아두이노처럼 pinMode 설정도 하면 된다.
내용
실제 코드
void setup() {
//USE_SERIAL.begin(921600);
USE_SERIAL.begin(115200);
//Serial.setDebugOutput(true);
USE_SERIAL.setDebugOutput(true);
USE_SERIAL.println();
USE_SERIAL.println();
USE_SERIAL.println();
for(uint8_t t = 4; t > 0; t--) {
USE_SERIAL.printf("[SETUP] BOOT WAIT %d...\n", t);
USE_SERIAL.flush();
delay(1000);
}
/*WiFiMulti.addAP("EM1", "hjy01033557007");
//WiFi.disconnect();
while(WiFiMulti.run() != WL_CONNECTED) {
USE_SERIAL.print(".");
delay(100);
}*/
WiFi.mode(WIFI_STA);
WiFi.begin("EM1", "hjy01033557007");
Serial.println("\nConnecting");
while(WiFi.status() != WL_CONNECTED){
Serial.print(".");
delay(100);
}
USE_SERIAL.println();
String ip = WiFi.localIP().toString();
USE_SERIAL.printf("[SETUP] WiFi Connected %s\n", ip.c_str());
// server address, port and URL
socketIO.begin("192.168.0.19", 8080, "/socket.io/?EIO=4");
// event handler
socketIO.onEvent(socketIOEvent);
}
loop() 함수는 코드 한 줄만 추가하고 자신이 실행하고 싶은 코드를 작성하면 된다.
예제코드에서는 이벤트를 아두이노에서 보내는 코드도 있다. 이 코드는 간단하게 주석으로 설명하고 넘어가겠다. 아래 코드를 참고해주면 좋겠다.
실제 코드
//일정 시간마다 socketIO 이벤트를 전송하는데, 전에 작동했던 시간을 저장하는 변수이다.
//unsigned long messageTimestamp = 0;
void loop() {
socketIO.loop();
//현재의 실행시간을 반환하여 변수에 저장한다.
/*uint64_t now = millis();
//작동한지 일정 시간이 흐르면 재작동하는데, 아래의 코드 상으로는 2초마다 재작동한다.
if(now - messageTimestamp > 2000) {
messageTimestamp = now;
// creat JSON message for Socket.IO (event)
//SocketIO로 보낼 JSON 메시지(=Event) 객체를 생성한다.
DynamicJsonDocument doc(1024);
JsonArray array = doc.to<JsonArray>();
// add evnet name
// Hint: socket.on('event_name', ....
//객체에 event_name을 추가한다. 이벤트 처리함수의 매개변수 중 type에 해당하는 부분이다.
array.add("event_name");
// add payload (parameters) for the event
//객체에 데이터를 추가한다. 이벤트 처리함수의 매개변수 중 payload에 해당하는 부분이다.
JsonObject param1 = array.createNestedObject();
param1["now"] = (uint32_t) now;
// JSON to String (serializion)
//JSON 메시지를 문자열로 직렬화한다.
String output;
serializeJson(doc, output);
// Send event
//직렬화한 메시지를 송신(전송)한다.
socketIO.sendEVENT(output);
// Print JSON for debugging
//보낸 메시지를 시리얼 모니터에 출력하여 확인한다.
USE_SERIAL.println(output);
}*/
}
! 위의 내용은 개인의 경혐과 지식을 바탕으로 작성된 것임을 알려드립니다.
! 참고
아두이노에서 Socket.IO 사용해보기
[socket.io] 프로젝트 준비2 - 아두이노 Socket.io