[Node-red] Schedule node 수정 - 3

2022. 11. 21. 11:42개발/Node-red

마지막 수정 후 보완할 점들

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

이외에도 여러가지 보완할 점들이 많이 보여서 수정한다.


스케쥴 알림 수정

 

사용자가 노드에 스케쥴을 설정 후 실행 했는데

현재 시간이 아직 설정한 시작 시간이 되지 않은 경우 실행문

        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.
            //client.publish(inTopic,"error testing 1");
            //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다1.');
            // 2022-11-17 이 부분 주석처리. 불필요한 메시지

        }

사용자가 노드에 스케쥴을 설정 후 실행 했는데

이미 현재 시간이 설정한 시작 시간을 지났을 때 실행문

        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
            //client.publish(inTopic,"error testing 2");
            //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다2.');    
        }

 

구현하고자 하는 기능은, 사용자가 스케쥴을 설정했을 때

아직 설정 시간이 되지 않았으면 '스케쥴 시작 전' 을 알리는 알림을 출력하고

 

시간이 흘러 설정 시간이 시작되면 '스케쥴 시작'을 알리는 알림을 출력하기 위해서

위와 같이 if else 문으로 구성했다.

 

시간을 입력했을 때 아직 시간이 되지 않았으면 자동으로 if문이 실행되고,

설정 시간이 시작되면 알아서 else문이 실행되는 방식을 생각했다.

 

하지만 위 조건문들이 실행되는 Node-red의 플로우가 시작되는 순간 한 번 뿐이다.

따라서 특정 if 조건문 하나만 실행된다.

 

내가 원하는 기능을 구현하기 위해서는 비동기식 처리 setTimeout을

수정해서 사용해야 할 것 같다.

 

* 코드 수정 - 1

        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() { // 이 함수 추가
                node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n실행됩니다.'); 
            }, 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.
            //client.publish(inTopic,"error testing 1");
            //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다1.');
            // 2022-11-17 이 부분 주석처리. 불필요한 메시지

        }

설정한 시작 시간이 되지 않았을 경우 if문이 실행되는데

그 if문 내부에 setTimeout 기능을 하나 추가했다.

 

sTimestamp - curTimestamp -> 설정한 시작 시간 - 현재 시간, 즉 시작 시간이 되면

node.warn("등록하신 스케쥴\n시작 : " + start + '\n종료 : ' + end + '\n실행됩니다.'); 로

메시지를 출력하도록 했다.

* 수정 - 1 실행결과

노드 설정
메시지 출력

설정된 시간 전에는 '스케쥴 시작 전 입니다'

설정된 시간이 되면 '등록하신 스케쥴 실행됩니다' 메시지가

setTimeout으로 인해 정상적으로 출력된다.

 

나머지 부분들도 수정한다.

 

* 코드 수정 - 2

        if (curTimestamp < sTimestamp) { //timer hasn't started (considering the case where the flow has been restarted)
            node.warn("스케쥴 시작 전 입니다");
            
            setTimeout(function() {
                node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n실행됩니다.');
                publishMessage(item, client, inTopic, config);
            }, sTimestamp - curTimestamp);
     
            setTimeout(function() {
            node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n끝났습니다.'); 
                for (var i = 0; i < 4; i++) {
                    client.publish(inTopic, offLoad[i]);
                }
                
            }, eTimestamp - curTimestamp); //turn all ports off when the schedule has been finished.

        }

위와 같이 setTimeout 을 한 개로 줄여서 코드를 간단하게 만들었다.

그리고 종료시간이 됐을 때 종료를 알리는 메시지를 추가했다.

 

나머지 처리문도 수정했다.

        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() {
                node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\n끝났습니다.'); 
                for (var i = 0; i < 4; i++) {
                    client.publish(inTopic, offLoad[i]);
                }
            }, eTimestamp - curTimestamp); //reset all ports
            //client.publish(inTopic,"error testing 2");
            //node.warn("등록하신 스케쥴 " + String(node.start_time) + '~' + String(node.end_time) + '이 끝났습니다2.');    
        }

현재 시간이 노드에 설정한 시간 범위에 포함됐을 때

사용자 입장에서 어쨋든 그 시간에는 동작하고 싶어 할 테니

중복으로 데이터를 전송해도 상관없다고 판단해서

시작 시간이 딱 들어맞지 않아도 범위에 포함되면 publishMessage 함수를 실행한다.

        else if (curTimestamp > eTimestamp) {
            node.warn("등록하신 스케쥴\n시작 : "  + start + '\n종료 : ' + end + '\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.
            //client.publish(inTopic,"error testing 3");
            
        }

사용자가 설정한 시간이 이미 지나간 시간에는

굳이 전체 릴레이를 off 하는 offLoad[ i ] 배열을 전송할 필요가 없다고 판단해서

모든 처리를 없애고 메시지로 시간 재설정을 알리도록 수정했다.

 

* 수정 - 2 실행결과

 

 

-아직 설정한 시간이 되지 않았을 때

노드 설정

위와 같이 노드의 스케쥴을 설정 하면 ( 현재 시간 오전 10:56 )

메시지 출력

설정 시간이 아직 되지 않았으므로 시작 전 을 알리는 메시지 출력

 

시작시간 됐을 때 메시지

시작 시간이 되면 설정한 기능 출력

 

종료시간 됐을 때 메시지

종료 시간이 되면 전체 초기화 데이터를 출력한다. 모두 정상적으로 동작한다.


 

-이미 현재 시간이 설정한 시간 범위 포함될 때

노드 설정

위와 같이 노드를 설정한다. ( 현재 시간 오전 11:01 )

메시지 출력

이미 설정 범위 내의 시간이므로

동작 기능을 실행한다.

종료시간 됐을 때 메시지

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


-현재 시간이 이미 설정한 종료 시간을 지났을 때

노드 설정

위와 같이 노드를 설정한다. (현재 시간 오전 11:01 )

메시지 출력

위와 같이 메시지가 정상적으로 출력된다.


스케쥴 알림 수정 - 2

노드 설정

노드를 위와 같이 설정한다. 필요한 기능을 체크하면

        if (!sTimestamp && !eTimestamp) { //form is empty, bring inputs to the current schedule
            console.log('warning');
            node.warn('전달된 페이로드가 없습니다. 스케쥴 날짜를 페이로드로 넘기거나, 노드 설정에서 스케쥴 날짜를 선택해주세요.');
            //node does not have the property of the schedule inputs, so warn the user.
        }

        else {
            item.push(config.heat);
            item.push(config.cool);
            item.push(config.exha);
            item.push(config.led); 
        }

이 코드의 else 문에서 push 명령어로 배열에 index를 추가한다.

    function publishMessage(item, client, inTopic, config) {
        client.publish(inTopic, '{\"mac\":' + "\""+ config.id + "\"" + ", \"type\":100" + ", \"outNo\" :0" + ", \"value\" :" + String(item[0]) + '}');
        client.publish(inTopic, '{\"mac\":' + "\""+ config.id + "\"" + ", \"type\":100" + ", \"outNo\" :1" + ", \"value\" :" + String(item[1]) + '}');
        client.publish(inTopic, '{\"mac\":' + "\""+ config.id + "\"" + ", \"type\":100" + ", \"outNo\" :2" + ", \"value\" :" + String(item[2]) + '}');
        client.publish(inTopic, '{\"mac\":' + "\""+ config.id + "\"" + ", \"type\":100" + ", \"outNo\" :3" + ", \"value\" :" + String(item[3]) + '}');
        console.log(item[0], item[1], item[2], item[3]);
    }

그리고 publishMessage( ) 함수에 의해 

String(item[ 0 ~ 3]) 형식( 코드를 오른쪽으로 드래그하면 보임 )으로 value key 의  값을 전송한다.

 

하지만 노드 설정에서 체크를 하지 않은 나머지 기능들은

Json 방식으로 수신되지 않고 아래와 같이 String 으로 수신된다.

체크한 기능만 JSON 으로 출력

두번째 메시지는 이전에 노드를 설정했을 때 한 번 체크했다가 풀었더니 JSON으로 들어온 모습이다.

 

  • 체크박스를 한번도 건드리지 않은 기능
  • 현재 체크되지 않은 기능

들은 item [ ] 배열이 null 인 상태라서 "value" key의 값이 존재하지 않아서 JSON형식이 깨지는 것이다.

이를 수정한다.

 

* 코드 수정 - 1

        else {
            item.push(config.heat);
            item.push(config.cool);
            item.push(config.exha);
            item.push(config.led);

            for (var i = 0; i < 4; i++) {
                if(item[i]==false){
                    item[i]="false";
                }
            }
        }

for 문을 추가했다.

item[ ] 배열의 0~3 index를 확인하는 처리를 추가했는데

만약 특정 item 배열의 index가 false 일 때

그냥 바로 String 형식의 'false' 를 저장하도록 했다.

 

하지만 동작을 하지 않는다.

 

*문제점

item[ i ]==false 는 체크가 되지 않은 상태일 때를 나타냄.

  • 체크박스를 한번도 건드리지 않은 기능
  • 현재 체크되지 않은 기능

데이터가 들어오지 않는 위 두가지 경우 중에서

두번째 상태만 해당됨.

 

한 번도 건드리지 않은 것들은 false조차 아닌채로 입력되는 듯 함.

 

* 코드 수정 - 2

        else {
            item.push(config.heat);
            item.push(config.cool);
            item.push(config.exha);
            item.push(config.led);

            for (var i = 0; i < 4; i++) {
                if(item[i]==null){  // 기존 if(item[i]==false) 에서 수정
                    item[i]=false;
                }
            }
        }

for문 내부를 수정했다.

item[ i ]==false 에서 item [ i ]==null 로 수정했다.

한 번도 건드리지 않은 체크박스들은 null 으로 인식된다 생각했다.

 

하지만 동작을 하지 않는다.

아마 null이거나 undefined 거나 아예 이상한 값으로 처리된다고 가정하고

다시 코드를 수정했다.

 

* 코드 수정 - 3

        else {
            item.push(config.heat);
            item.push(config.cool);
            item.push(config.exha);
            item.push(config.led);

            for (var i = 0; i < 4; i++) {
                if(item[i]!==true){		// 기존 if(item[i]==null) 에서 수정
                    item[i]=false;
                }
            }
        }

위와 같이 수정했다. 어차피 사용할 기능은 확실하게 체크가 되므로 true 로 들어온다.

따라서 그렇지 않은 경우. 즉,

  • 체크 안 된 나머지 기능
  • 한 번도 건드리지 않은 기능 ( null? undefined? )

두 가지는 true 가 아니므로 !==true 를 사용했다.

 

* 코드 수정 - 3 결과

노드 설정

체크박스는 기존 상태에서 건드리지 않았다.

한 번도 건드리지 않은 값들을 그대로 유지해야 되기 때문.

메시지 출력

성공적으로 출력된다. 이게 되네

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

[Node-red] Custom node 배포  (0) 2022.12.01
[Node-red] Schedule node 수정 - 4  (0) 2022.11.21
[Node-red] Schedule node 수정 - 2  (0) 2022.11.17
[Node-red] Schedule node 수정-1  (0) 2022.11.16
[Node-red] Schedule node 소스 분석  (0) 2022.11.16