[Node-red] Schedule node 수정 - 2

2022. 11. 17. 10:49개발/Node-red

https://iruk.tistory.com/18

 

Custom node 수정-1

https://iruk.tistory.com/8 Node-red Custom node 소스 분석 Inject 로 시간 데이터를 입력하거나 노드 내에서 html Schedule 기능으로 동작구현. 특정 시간에 동작시키는 기능. MQTT 무선통신으로 ESP32 에 데이터전

iruk.tistory.com

이전 포스팅에 이어서 수정을 진행한다.

이전 단계에서, 노드 내부 설정에서 Mac address 를 기입했을 때 오류가 발생했다.

그래서 위 사진처럼 mac 값을 소스에 강제로 'test'로 기입했다.

하지만 이런 식으로 "mac" key의 value 문자열이 " " 로 반환되지 않는다.

이 오류들을 수정한다.

 

Json 객체 포맷 수정

var offLoad = [
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :0" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :1" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :2" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :3" + ", \"value\" :0" + '}'
]; //turns all ports off

위 사진처럼 "mac" 의 value를 test로 강제 입력 했었는데, test가 문자열 형식이

아니라서 Json 객체변환이 불가능 한 것 같다.

 

Json 객체 포맷 수정하면서 config.id오류로 임의로 'test'를 기입했던 부분도 수정한다.

var offLoad = [
	'{\"mac\":' +  '\"'+ config.id + '\"' + ", \"type\":100" + ", \"outNo\" :0" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :1" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :2" + ", \"value\" :0" + '}',
	'{\"mac\": test' + ", \"type\":100" + ", \"outNo\" :3" + ", \"value\" :0" + '}'
]; //turns all ports off

위와 같이 수정했다. 'test' 대신 원래대로 config.id( 노드 입력 Mac address )로 수정했고

첫번째 index만 config.id 양단에 \" 를 추가해주었다.


config.id 수정 후 결과

debug 36 부분에 정상적으로 outNo:0 에 대한 Json 객체가 출력된다.

나머지 outNo 데이터는 초기 오류대로 String 으로 출력된다.

나머지 데이터도 마찬가지로 수정해준다.


출력 메시지 최종 수정

var offLoad = [
	'{\"mac\":' +  '\"'+ config.id + '\"' + ", \"type\":100" + ", \"outNo\" :0" + ", \"value\" :0" + '}',
	'{\"mac\":' +  '\"'+ config.id + '\"' + ", \"type\":100" + ", \"outNo\" :1" + ", \"value\" :0" + '}',
	'{\"mac\":' +  '\"'+ config.id + '\"' + ", \"type\":100" + ", \"outNo\" :2" + ", \"value\" :0" + '}',
	'{\"mac\":' +  '\"'+ config.id + '\"' + ", \"type\":100" + ", \"outNo\" :3" + ", \"value\" :0" + '}'
]; //turns all ports off

데이터 포맷 뿐만 아니라, 불필요한 메시지를 없애고

함수가 어디서 실행되는지 찾기 위해서 특정 메시지를 추가했다.

testing error 1 ~ 3 메시지를 client.publish로 확인한다.

sTimestamp = new Date(start).getTime(); //stime timestamp
eTimestamp = new Date(end).getTime(); //etime timestamp

if (curTimestamp < sTimestamp) { //timer hasn't started (considering the case where the flow has been restarted)
       setTimeout(function() {
          publishMessage(item, client, inTopic, config);
       }, sTimestamp - curTimestamp);
                
       setTimeout(function() {
           for (var i = 0; i < 4; i++) {
               client.publish(inTopic, offLoad[i]);
           }
       }, eTimestamp - curTimestamp); //turn all ports off when the schedule has been finished.

//node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.')
/* 윗부분 주석처리! 불필요한 메시지. 시간값이 잘못 설정 됐을 경우는 괜찮은 메시지긴 하지만
지금은 불필요함. */
client.publish(inTopic,"error testing 1"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}

else if (curTimestamp >= sTimestamp && curTimestamp <= eTimestamp) { //schedule has been up and running
       //{"mac":"048e741c5210","type":100,"outNo":2,"value":1}
       publishMessage(item, client, inTopic, config);
       setTimeout(function() {
           for (var i = 0; i < 4; i++) {
               client.publish(inTopic, offLoad[i]);
           }
       }, eTimestamp - curTimestamp); //reset all ports
            
       node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');    
client.publish(inTopic,"error testing 2"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}

else if (curTimestamp > eTimestamp) {
       for (var i = 0; i < 4; i++) {
           client.publish(inTopic, offLoad[i]);
       } //reset all ports since the schedule has already been finished. Just in case the ports were not reset.
client.publish(inTopic,"error testing 3"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}

위와 같이 client.publish(inTopic, "error testing 3"); 등의 메시지를 추가해서

동작 위치를 확인하기 용이하도록 했다.


최종 타이머 동작 확인

위와 같이 노드를 설정한다. 시작시간, 종료시간, Cooling 기능 체크.

 

1. 스케쥴 시작 전

error testing 1 이 정상적으로 출력된다.

error testing 1 은 현재 시간이, 타이머의 시작 시간보다 작을 때 출력이다.

 

2. 스케쥴 시작

체크한 Cooling 기능 (outNo : 1 )이 정상적으로 JSON 객체로 출력.

나머지 기능 (outNo ) 들은 JSON이 아닌 String으로 출력됨.

추후에 JSON 인지 String 인지 구분하는 처리를 추가해서

필요한 데이터만 전송하도록 수정할 예정.

 

3. 스케쥴 종료

타이머 종료시간이 되면, 모든 outNo 들을 0 출력해서 OFF 한다.

이로써 MQTT 통신 출력데이터는 정상적으로 handle할 수 있다.


시작 알림 메시지 오류

1. 타이머 시작 전 에 출력되는 메시지다.

시작시간 ~ 종료시간이 undefined로 출력된다. 소스코드를 살펴보았다.

node.warn('등록하신 스케쥴을 시작합니다. (' + node.startTime + '~' + String(node.endTime) + ')');

if (curTimestamp < sTimestamp) { //timer hasn't started (considering the case where the flow has been restarted)
       setTimeout(function() {
          publishMessage(item, client, inTopic, config);
       }, sTimestamp - curTimestamp);
                
       setTimeout(function() {
           for (var i = 0; i < 4; i++) {
               client.publish(inTopic, offLoad[i]);
           }
       }, eTimestamp - curTimestamp); //turn all ports off when the schedule has been finished.

//node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.')
/* 윗부분 주석처리! 불필요한 메시지. 시간값이 잘못 설정 됐을 경우는 괜찮은 메시지긴 하지만
지금은 불필요함. */
client.publish(inTopic,"error testing 1"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}

코드 최상단에 node.warn( ) 부분에서 출력되는 것 같다.

현재시간으로 if 문 처리하기 전에 node.warn( )이 먼저 실행된다.

 

시작 시간 = node.startTime

종료 시간 = node.endTime 으로 받아오는데, undefined로 출력되는게 이상하다.

if (curTimestamp < sTimestamp)

이 부분의 시작시간 ( sTimestamp )은

var start = String(config.startTime);
sTimestamp = new Date(start).getTime(); //stime timestamp

이 선언으로 정상적으로 처리된다.

따라서, undefined가 발생하는 node.startTime 이 아닌, start변수로 수정해야되나?


시작 알림 메시지 수정

node.warn('등록하신 스케쥴을 시작합니다!!! (' + start + '~' + String(node.endTime) + ')');

위와 같이 수정해보았다.

오류를 수정했다!! 나머지 endTime 도 수정했다.

node.warn('등록하신 스케쥴을 시작합니다!!! (' + start + '~' + end + ')');

위와 같이 시작시간 ~ 종료시간 이 정상적으로 출력됐다.

깔끔하게 출력되도록 소스를 좀 더 수정했다.

node.warn('노드 스케쥴 설정 되었습니다.\n시작 : ' + start + '\n종료 : ' + end );
node.warn('노드 스케쥴 설정 되었습니다.\n시작 : ' + start + '\n종료 : ' + end );

if (curTimestamp < sTimestamp) { //timer hasn't started (considering the case where the flow has been restarted)
       node.warn("스케쥴 시작 전 입니다");
       setTimeout(function() {
          publishMessage(item, client, inTopic, config);
       }, sTimestamp - curTimestamp);
                
       setTimeout(function() {
           for (var i = 0; i < 4; i++) {
               client.publish(inTopic, offLoad[i]);
           }
       }, eTimestamp - curTimestamp); //turn all ports off when the schedule has been finished.

//node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.')
/* 윗부분 주석처리! 불필요한 메시지. 시간값이 잘못 설정 됐을 경우는 괜찮은 메시지긴 하지만
지금은 불필요함. */
//client.publish(inTopic,"error testing 1"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}

node.warn( "스케쥴 시작 전 입니다"); 추가

else if (curTimestamp >= sTimestamp && curTimestamp <= eTimestamp) { //schedule has been up and running
       //{"mac":"048e741c5210","type":100,"outNo":2,"value":1}
       node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n실행됩니다.'); 
       publishMessage(item, client, inTopic, config);
       setTimeout(function() {
           for (var i = 0; i < 4; i++) {
               client.publish(inTopic, offLoad[i]);
           }
       }, eTimestamp - curTimestamp); //reset all ports
            
       //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');    
//client.publish(inTopic,"error testing 2"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}
node.warn("등록하신 스케쥴\n시작 : " + start + '\n종료 : ' + end + '\n실행됩니다.'); 추가
else if (curTimestamp > eTimestamp) {
node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n끝났습니다.');
       for (var i = 0; i < 4; i++) {
           client.publish(inTopic, offLoad[i]);
       } //reset all ports since the schedule has already been finished. Just in case the ports were not reset.
//client.publish(inTopic,"error testing 3"); // 이 부분 추가. 메시지 발생위치 찾기 위함
}​

node.warn("등록하신 스케쥴\n시작 : " + start + '\n종료 : ' + end + '\n끝났습니다.'); 추가

 

수정 후 출력 확인

스케쥴 시작 전일 때
스케쥴 실행 중일 때
스케쥴 종료 후

위와 같이 정상적으로 동작한다.


잔여 오류 및 보완할 점

  • mqtt 통신 불안정
  • mqtt 통신 불안정에 따른 Node-red 서버 중지 ( cmd 에서 자주 node-red 종료 )
  • 스케쥴 시작 알림에 어떤 기능의 스케쥴인지 알려주면 좋을 것 같음
  • 노드 설정으로 동작시키는 경우 제외하고 외부 inject로도 동작하면 좋을 것 같음
 
 

'개발 > Node-red' 카테고리의 다른 글

[Node-red] Schedule node 수정 - 4  (0) 2022.11.21
[Node-red] Schedule node 수정 - 3  (0) 2022.11.21
[Node-red] Schedule node 수정-1  (0) 2022.11.16
[Node-red] Schedule node 소스 분석  (0) 2022.11.16
Node-red 윈도우 설치  (0) 2022.11.14