[Node-red] Relay node 제작 - 2

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 데이터의 최대 크기를

고려하지 않은게 실수였다.

 

정상적으로 동작해서 다행