[Node-red] Schedule node 수정 - 4

2022. 11. 21. 15:37개발/Node-red

2022.11.21 - [기록/개발 노트] - [Node-red] Custom node 수정 - 3

 

[Node-red] Custom node 수정 - 3

마지막 수정 후 보완할 점들 mqtt 통신 불안정 mqtt 통신 불안정에 따른 Node-red 서버 중지 ( cmd 에서 자주 node-red 종료 ) 스케쥴 시작 알림에 어떤 기능의 스케쥴인지 알려주면 좋을 것 같음 노드 설

iruk.tistory.com

이전 수정 단계에 이어서 진행한다.

이전 단계에서는 스케쥴을 노드 내부에서 설정했을 때

출력되는 메시지를 수정했다.

 

스케쥴이 작동하는 방식은 2가지인데

  • 노드 내부 설정
  • 노드 외부 JSON 데이터 입력

이번에는 외부에서 JSON 으로 데이터를 입력해서 구동시키는 방식을 수정한다.


노드 외부에서 스케쥴 데이터 입력

            console.log(msg.payload);
            //var pLoad = JSON.parse(msg.payload);
            var pLoad = msg.payload;

            if (sTimestamp || eTimestamp) {
                node.warn('페이로드로 날짜를 전달할 때는 노드 설정의 스케쥴을 비워주세요.');
            }

            else if (pLoad.start_time != undefined && pLoad.end_time != undefined) {
                //{"start_time" : "", "end_time" : "" ,"outNo" : 2, "value" : 1} -> {"mac":"048e741c5210","type":100,"outNo":2,"value":1}
                node.start_time = pLoad.start_time;
                node.end_time = pLoad.end_time;

                var stime = new Date(node.start_time).getTime();
                var etime = new Date(node.end_time).getTime();


                var cur = Date.now();
                node.warn('등록하신 스케쥴을 시작합니다. (' + String(node.start_time) + '~' + String(node.end_time) + ')');
                var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"type\" : 100,\"outNo\" : " + String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}"; 
                
                if (cur < stime) { //timer hasn't started (considering the case where the flow has been restarted)

                    setTimeout(function() {
                        client.publish(inTopic, msg_toPublish);
                    }, stime - cur);
                        
                    setTimeout(function() {
                        for (var i = 0; i < 4; i++) {
                            client.publish(inTopic, offLoad[i]);
                        }
                    }, etime - cur); //turn all ports off when the schedule has been finished.
                    node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');

                } else if (cur >= stime && cur <= etime) { //schedule has been up and running
                    //{"mac":"048e741c5210","type":100,"outNo":2,"value":1}
                    client.publish(inTopic, msg_toPublish);

                    setTimeout(function() {
                        for (var i = 0; i < 4; i++) {
                            client.publish(inTopic, offLoad[i]);
                        }
                    }, etime - cur); //reset all ports
                    node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');

                } else if (cur > etime) {

                    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.
                }

                else {
                    //node.send("nothing happened");
                } //do nothing since case does not exist.
            }
            //client.publish(inTopic, msg.payload);
            //node.send(msg);

노드 외부에서 데이터가 Inject 되는 경우의 함수다.

먼저 외부에서 데이터를 입력하는 경우를 확인해본다.

위와 같이 노드 설정의 스케쥴을 모두 비운다.

그리고 외부에서 입력할 JSON 데이터를 생성한다.

msg.payload=
{ "start_time" : "2022-11-21 14:52", 
    "end_time": "2022-11-21 14:53", 
"outNo" : 2, "value" : 1 };
return msg;

Node-red 의 function 노드에 위와 같이 입력 후 실행한다. ( 현재 시간 11/21 14:51 )

스케쥴이 시작하기 전에 위와 같은 메시지가 출력된다.

끝나기도 전에 끝났다는 메시지가 먼저 출력된다.

메시지가 출력되고 나서 이후에 시작 시간이 되면 데이터가 출력된다.

메시지가 출력되는 타이밍이 이상해 보인다.

종료 시간이 되면 정상적으로 전체 초기화 데이터도 출력된다.

데이터의 출력은 문제가 없는데 메시지가 이상한 타이밍에 출력되는게 문제다.


소스 코드 수정

            if (sTimestamp || eTimestamp) {
                node.warn('페이로드로 날짜를 전달할 때는 노드 설정의 스케쥴을 비워주세요.');
            }

            else if (pLoad.start_time != undefined && pLoad.end_time != undefined) {
                //{"start_time" : "", "end_time" : "" ,"outNo" : 2, "value" : 1} -> {"mac":"048e741c5210","type":100,"outNo":2,"value":1}
                node.start_time = pLoad.start_time;
                node.end_time = pLoad.end_time;

                var stime = new Date(node.start_time).getTime();
                var etime = new Date(node.end_time).getTime();


                var cur = Date.now();
                //node.warn("등록하신 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n실행됩니다.');
                node.warn('등록하신 스케쥴을 시작합니다. (' + String(node.start_time) + '~' + String(node.end_time) + ')');
                var msg_toPublish = '{\"mac\" : ' + "\"" + String(config.id) + "\",\"type\" : 100,\"outNo\" : " + String(pLoad.outNo) + ",\"value\" : " + String(pLoad.value) + "}"; 
                
                if (cur < stime) { //timer hasn't started (considering the case where the flow has been restarted)

소스 초반부를 살펴보았다. 

if (sTimestamp || eTimestamp) {
	node.warn('페이로드로 날짜를 전달할 때는 노드 설정의 스케쥴을 비워주세요.');
}

노드 내부 설정 시작/종료 시간값인 sTimestamp eTimestamp 둘 중 하나라도 존재할 시

시간값 충돌을 방지하기 위해 알림 메시지를 출력해준다.

 

그리고 둘 다 없는채로 외부 Inject가 들어오면 else if 문이 실행되는데

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

위 코드가 조건없이 실행되기 때문에 불필요한 메시지가 출력되는 것이었다.

이 메시지를 아래와 같이 수정했다.

node.warn("외부에서 입력한 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n이 설정되었습니다.');

시작되었다는 문구 대신, 외부에서 입력된 시간 데이터로 설정되었다는 메시지를  출력한다.

 

아직 시작시간 되지 않았을 때

                if (cur < stime) { //timer hasn't started (considering the case where the flow has been restarted)

                    setTimeout(function() {
                        client.publish(inTopic, msg_toPublish);
                    }, stime - cur);
                        
                    setTimeout(function() {
                        for (var i = 0; i < 4; i++) {
                            client.publish(inTopic, offLoad[i]);
                        }
                    }, etime - cur); //turn all ports off when the schedule has been finished.
                    node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');

                }

외부에서 입력된 시간 데이터의 시작 시간이 아직 되지 않았을 때의 처리문이다.

node.warn( )에 의해서 시간이 되든 말든 if문이 끝나면 메시지가 출력된다.

setTimeout 명령어는 시간이 되기 전까지 대기를 하지만

node.warn 은 대기 없이 바로 메시지를 출력해서 자꾸 메시지가 먼저 출력되는 것 같다.

 

수정

                if (cur < stime) { //timer hasn't started (considering the case where the flow has been restarted)
                    node.warn("외부입력 스케쥴 시작 전 입니다");

                    setTimeout(function() {
                        node.warn("등록하신 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n실행됩니다.');
                        client.publish(inTopic, msg_toPublish);
                    }, stime - cur);
                        
                    setTimeout(function() {
                        node.warn("등록하신 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n끝났습니다.');
                        for (var i = 0; i < 4; i++) {
                            client.publish(inTopic, offLoad[i]);
                        }
                    }, etime - cur); //turn all ports off when the schedule has been finished.
                    //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');

                }

불필요한 메시지 출력을 주석처리하고

각각 상황에 맞게 메시지 출력을 생성했다.

 

동작 데이터는 setTimeout( )명령어에서 전부 관리되므로

데이터를 전송하기 전에 메시지를 먼저 출력하도록 수정했다.

 

외부에서 입력한 시작~종료 시간에 포함될 때

외부에서 입력한 시작~종료 시간을 지났을 때 모두 똑같은 메커니즘으로 수정했다.

                 else if (cur >= stime && cur <= etime) { //schedule has been up and running
                    //{"mac":"048e741c5210","type":100,"outNo":2,"value":1}
                    node.warn("외부입력 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n실행됩니다.');
                    client.publish(inTopic, msg_toPublish);

                    setTimeout(function() {
                        node.warn("외부입력 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n끝났습니다.');
                        for (var i = 0; i < 4; i++) {
                            client.publish(inTopic, offLoad[i]);
                        }
                    }, etime - cur); //reset all ports
                    //node.warn("외부입력 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다.');

                } else if (cur > etime) {
                    node.warn("외부입력 스케쥴\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n종료 시간이 이미 지났습니다.\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.
         			*/
        	    }

위와 같이 수정했다. 실행 결과를 살펴본다.

 

수정 후 결과확인

Node-red Flow

-현재 시간이 아직 시작시간 안됐을 때

msg.payload=
{ "start_time" : "2022-11-21 15:30", 
    "end_time": "2022-11-21 15:31", 
"outNo" : 2, "value" : 1 };
return msg;

Node-red function 노드의 입력값이다.

( 현재 시간 11/21 15:16 )

메시지 출력

정상적으로 동작한다.

 

 

-현재 시간이 입력된 시간 범위일 때

msg.payload=
{ "start_time" : "2022-11-21 15:31", 
    "end_time": "2022-11-21 15:32", 
"outNo" : 2, "value" : 1 };
return msg;

외부에서 입력된 시간 값이 현재 시간을 포함할 때를 확인한다.

(현재 시간 11/21 15:31)

메시지 출력

 

-현재 시간이 입력된 시간을 이미 지났을 때

msg.payload=
{ "start_time" : "2022-11-20 15:31", 
    "end_time": "2022-11-20 15:32", 
"outNo" : 2, "value" : 1 };
return msg;

11월 21일이 아니라 어제 날짜 ( 11월 20일 ) 로 해보았다.

시간을 이미 지났으므로 시간을 재설정하라는 메시지가 출력되어야 한다.

메시지 출력


전체 테스트

msg.payload=
{ "start_time" : "2022-11-21 15:35", 
    "end_time": "2022-11-21 15:36", 
"outNo" : 2, "value" : 1 };
return msg;

스케쥴 시작 전 부터 스케쥴 종료 후의 처리까지 검토해보았다.

( 현재시간 11/21 15:34 )

스케쥴 시작 전
스케쥴 시작
스케쥴 종료 및 전체 초기화 데이터

모두 정상적으로 동작한다.

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

[Node-red] Custom node 만드는 방법  (0) 2022.12.02
[Node-red] Custom node 배포  (0) 2022.12.01
[Node-red] Schedule node 수정 - 3  (0) 2022.11.21
[Node-red] Schedule node 수정 - 2  (0) 2022.11.17
[Node-red] Schedule node 수정-1  (0) 2022.11.16