2022. 12. 7. 11:09ㆍ개발/Node-red
2022.12.05 - [기록/개발 노트] - [Node-red] Relay node 제작
[Node-red] Relay node 제작
2022.11.21 - [기록/개발 노트] - [Node-red] Schedule node 수정 - 4 [Node-red] Schedule node 수정 - 4 2022.11.21 - [기록/개발 노트] - [Node-red] Custom node 수정 - 3 [Node-red] Custom node 수정 - 3 마지막 수정 후 보완할 점들 mq
iruk.tistory.com
Relay node를 제작하면서 오류가 있었다.
{"outNo" : 1, "value" : 0} 식의 JSON데이터가 수신되면
1번 릴레이를 off 하는 동작은 잘 됐지만
{"No0":1, "No1":0, "No2":1, "No3":1} 처럼
한 번에 모든 릴레이를 처리하는 데이터는 동작하지 않았다.
// 개별 릴레이 제어 데이터
var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"type\" : 100,\"outNo\" : "
+ String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}";
하나의 릴레이만 동작하는 데이터다.
위 데이터를 수신하는 아두이노 소스를 보면
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
sMsg="";
for (int i = 0; i < length; i++) {
sMsg+=(char)payload[i];
}
Serial.println(sMsg);
if(sMsg.indexOf("No0") > 0){
Serial.println("string test");
}
deserializeJson(doc,payload);
root = doc.as<JsonObject>();
int no = root["outNo"]; // 구분해서 들어오는 데이터
int value = root["value"];
if(no==0){
digitalWrite(heat_pin,value);
}
else if(no==1){
digitalWrite(cool_pin,value);
}
else if(no==2){
digitalWrite(exha_pin,value);
}
else if(no==3){
digitalWrite(led_pin,value);
}
위와 같이 root[ ] 명령어로 정상적으로 outNo와 value를 인식한다.
딱히 처리문에는 오류가 없는 것 같다
// 전체 릴레이 제어 데이터
var msg_toPublish2 = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"type\" : 100,\"No0\" : "
+ String(pLoad.outNo0) + ",\"No1\" : " + String(pLoad.outNo1) + ",\"No2\" : " + String(pLoad.outNo2)
+ ",\"No3\" : " + String(pLoad.outNo3) + "}";
하지만
위와 같이 데이터를 전송하면 No0 No1 No2 No3 를
ESP32가 인식하지 못한다.
if 문 처리의 오류일 수도 있지만
데이터의 길이가 너무 크다는 점을 원인으로 가정하여
오류를 수정해 보았다.
노드 출력 데이터 수정
var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"outNo\" : "
+ String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}";
var msg_toPublish2 = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"No0\" : "
+ String(pLoad.outNo0) + ",\"No1\" : " + String(pLoad.outNo1) + ",\"No2\" : " + String(pLoad.outNo2)
+ ",\"No3\" : " + String(pLoad.outNo3) + "}";
msg_toPublish2 의 데이터의 크기를 최소로 줄이기 위해
불필요한 key "type"을 제거했다.
if(root["No0"]){
Serial.println("test"); // mqtt 데이터를 node-red 에서 짧게 보내면 수신됨
}
Node-red 에서 MQTT 로 데이터를 전송한다.
제작한 노드를 거치지 않고
Direct 로 mqtt 노드를 사용했다.
아두이노에 test 메시지가 정상적으로 출력된다.
MQTT 송수신은 문제 없으므로
제작한 노드를 거쳐서 테스트 해본다.
오류
이번에는 제작한 노드로 전송해보았다.
하지만 데이터가 수신되지 않았다.
제작한 노드의 Topic은 수정한 적 없으므로
원인은 두 가지 같다.
1. 일시적인 네트워크 오류
2. 노드가 msg를 수신할 때 처리문 오류
일시적인 네트워크 오류 는
5분 동안 테스트 해본 결과 아닌 것 같다.
노드가 msg를 수신할 때 처리문을 살펴보았다.
node.on('input', function(msg) {
var pLoad = msg.payload;
var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"outNo\" : "
+ String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}";
var msg_toPublish2 = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"No0\" : "
+ String(pLoad.outNo0) + ",\"No1\" : " + String(pLoad.outNo1) + ",\"No2\" : " + String(pLoad.outNo2)
+ ",\"No3\" : " + String(pLoad.outNo3) + "}";
console.log(msg.payload);
if(pLoad.outNo != undefined && pLoad.value != undefined){
client.publish(inTopic, msg_toPublish);
}
else if(pLoad.outNo0 != undefined && pLoad.outNo1 != undefined && pLoad.outNo2 != undefined && pLoad.outNo3 != undefined){
client.publish(inTopic,msg_toPublish2);
}
});
input msg가 들어왔을 때
코드 하단의 if , else문에 의해서 처리 동작을 구분한다.
if 문은 outNo 와 value key가 들어왔을 때
즉 개별 릴레이를 제어할 때 처리문이다.
else 문에서 전체 릴레이를 제어할 때 조건이어야 하는데
outNo0 outNo1 outNo2 outNo3 key를 처리하고 있었다.
나는 지금 No0 No1 No2 No3 key를 아두이노 수신하는 가정 하에 처리했는데
노드에서 애초에 출력이 잘못되고 있었다.
수정 후 오류
if(pLoad.outNo != undefined && pLoad.value != undefined){
client.publish(inTopic, msg_toPublish);
}
else if(pLoad.No0 != undefined && pLoad.No1 != undefined && pLoad.No2 != undefined && pLoad.No3 != undefined){
client.publish(inTopic,msg_toPublish2);
}
위와 같이 else 문을 수정했다.
No0 No1 No2 No3 key를 받아 처리하도록 했다.
하지만 undefined 로 수신된다.
노드 소스를 다시 살펴보았다.
node.on('input', function(msg) {
var pLoad = msg.payload;
var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"outNo\" : "
+ String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}";
var msg_toPublish2 = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"No0\" : "
+ String(pLoad.outNo0) + ",\"No1\" : " + String(pLoad.outNo1) + ",\"No2\" : " + String(pLoad.outNo2)
+ ",\"No3\" : " + String(pLoad.outNo3) + "}";
console.log(msg.payload);
if(pLoad.outNo != undefined && pLoad.value != undefined){
client.publish(inTopic, msg_toPublish);
}
else if(pLoad.outNo0 != undefined && pLoad.outNo1 != undefined && pLoad.outNo2 != undefined && pLoad.outNo3 != undefined){
client.publish(inTopic,msg_toPublish2);
}
});
msg_toPublish2 데이터를 보면
pLoad.outNo0 pLoad.outNo1 pLoad.outNo2 pLoad.outNo3 로
입력 데이터를 구분하고 있었다.
이 또한 No0 No1 No2 No3로 수정하고
다시 테스트 해보았다.
1번 2번 릴레이를 on 하도록 데이터를 전송했다.
성공적으로 수신되었다.
1번 2번 릴레이가 정상적으로 동작한다.
MQTT 데이터가 너무 커서 동작하지 않았던 것 같다.
아두이노 처리문에서 좀 더 깔끔하게
코드를 수정했다.
for (int i = 0; i < length; i++) {
//Serial.print((char)payload[i]);
sMsg+=(char)payload[i];
}
Serial.println(sMsg); //출력
deserializeJson(doc,payload);
root = doc.as<JsonObject>();
int no = root["outNo"]; // 구분해서 들어오는 데이터
int value = root["value"];
int no0 = root["No0"];
int no1 = root["No1"];
int no2 = root["No2"];
int no3 = root["No3"];
if(sMsg.indexOf("outNo") > 0){
if(no==0){
digitalWrite(heat_pin,value);
}
else if(no==1){
digitalWrite(cool_pin,value);
}
else if(no==2){
digitalWrite(exha_pin,value);
}
else if(no==3){
digitalWrite(led_pin,value);
}
}
if(sMsg.indexOf("No0") > 0){
digitalWrite(heat_pin,no0);
digitalWrite(cool_pin,no1);
digitalWrite(exha_pin,no2);
digitalWrite(led_pin,no3);
}
sMsg.indexof 를 추가했다.
sMsg는 MQTT 로 수신받은 데이터의 String 값이고
indexof 는 String에서 어떤 값을 포함하는지
확인할 때 쓰이는 자체 함수이다.
따라서
수신된 데이터에 outNo가 있을경우( 개별 릴레이 )
수신된 데이터에 No0가 있을경우 ( 전체 릴레이 )
와 같이 수정했다.
결국 MQTT 데이터의 최대 크기를
고려하지 않은게 실수였다.
정상적으로 동작해서 다행
'개발 > Node-red' 카테고리의 다른 글
[Node-red] 새로운 릴레이 노드 제작 - 1 (0) | 2022.12.21 |
---|---|
[Node-red] Schedule 노드 ( mqtt x ) 제작 (0) | 2022.12.09 |
[Node-red] Relay node 제작 (0) | 2022.12.05 |
[Node-red] Custom node 만드는 방법 (0) | 2022.12.02 |
[Node-red] Custom node 배포 (0) | 2022.12.01 |