[Node-red] Schedule 노드 ( mqtt x ) 제작

2022. 12. 9. 13:03개발/Node-red

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 마지막 수정 후 보완할 점들 mqtt 통신 불안정 mqtt 통신 불안정에 따른 Node-red 서버 중지 ( cmd 에서 자주 node-red 종료

iruk.tistory.com

전에 MQTT 통신을 사용하는 Schedule 노드를 제작했었다.

이번에는 MQTT 기능을 제외하고

단순히 schedule 시간 설정에 따라 메시지를 출력하는

심플한 노드를 제작해볼 것이다.


.html 파일

<script type="text/html" data-template-name="스케쥴노드">
    <div class="form-row">
        <label for="node-input-name"><i class="fa fa-tag"></i> 이름</label>
        <input type="text" id="node-input-name" placeholder="이름">
    </div>
    <div class="form-row">
        <label for="node-input-startTime"><i class="fa fa-calendar"></i> 가동 시작 시간 (언제부터)<span data-i18n="common.label.startTime"></span></label>
        <input type="datetime-local" id="node-input-startTime">
    </div>
    <div class="form-row">
        <label for="node-input-endTime"><i class="fa fa-calendar"></i> 가동 완료 시간 (언제까지)<span data-i18n="common.label.endTime"></span></label>
        <input type="datetime-local" id="node-input-endTime">
    </div>

    </br>
    <div class="form-tips"><b>도움말</b>
    </br> 시간 설정은 2가지 방식이 있습니다.
    </br> <b>1) 노드 내부 설정</b>
    </br> 위에 있는 시작시간 / 종료시간 을 상황에 맞게 설정해주세요.
    </br> <b>2) 노드 외부 설정</b>
    </br> { "start_time" : "2022-12-08 12:43", "end_time": "2022-12-08 12:44" } 형식으로 입력해주세요.
</div>
</script>

<script type = "text/html" data-help-name = "스케쥴노드">
    <p>메시지를 스케쥴 시간에 따라 출력하는 노드입니다.</p>
    <h3>출력</h3>
        <dl class = "message-properties">
        <dt>payload
            <span class = "property-type">string | buffer</span>
        <dd>
            설정된 시간이 되면 1, 종료 시 0 이 출력됩니다.</p>
        </dt>
    <h3>주의사항</h3>
    <p>노드에 시간 데이터를 입력하실 때는 노드 내부 설정을 비워주시기 바랍니다.</p> 
</script>

위와 같이 노드를 열었을 때 Schedule 설정을 할 수 있도록 한다.


.js 파일

javascript 처리는 2가지 종류가 있다.

 

1) 노드 내부에서 시간 설정할 때

2) 노드 외부에서 시간 입력할 때

 

1번 경우부터 작성한다.

 

1) 노드 내부에서 시간 설정

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

            setTimeout(function() {
                node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n실행됩니다.');
                msg.payload=1;
                node.send(msg);
            }, sTimestamp - curTimestamp);
           
            setTimeout(function() {
                node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n끝났습니다.'); 
                msg.payload=0;
                node.send(msg);
            }, eTimestamp - curTimestamp);

        } else if (curTimestamp >= sTimestamp && curTimestamp <= eTimestamp) { //schedule has been up and running

            node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n실행됩니다.'); 
            setTimeout(function(){
                msg.payload=1;
                node.send(msg);
            }, 0);

            setTimeout(function() {
                node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n끝났습니다.'); 
                msg.payload=0;
                node.send(msg);
            }, eTimestamp - curTimestamp);

        } else if (curTimestamp > eTimestamp) {
            node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n종료 시간이 이미 지났습니다.\n시간을 확인 후 재설정 해주세요.'); 
            
        }

전에 작성했던 MQTT Schedule 노드와 마찬가지로

 

현재 시간이 아직 설정한 시간이 아닐 때

현재 시간이 이미 설정 시간 범위일 때

현재 시간이 설정 시간 지났을 때

 

세 가지 상황이 있다.

 

각각 상황마다 필요한 안내 메시지를 출력한다.

스케쥴 시작할때는 1

종료 시에는 0 을 출력하도록 한다.


노드 외부에서 시간 입력

//Node-red function 코드
msg.payload=
{ "start_time" : "2022-12-09 11:52", 
    "end_time": "2022-12-09 11:53"};
return msg;
// Custom node 소스

setTimeout(function() {
	node.warn("외부입력 스케쥴\n***********************\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n***********************\n실행됩니다.');
	msg.payload=1;
	node.send(msg);
}, stime - cur);

setTimeout(function() {
	node.warn("외부입력 스케쥴\n***********************\n시작 : "  + String(node.start_time) + '\n종료 : ' + String(node.end_time) + '\n***********************\n끝났습니다.');
	msg.payload=0;
	node.send(msg);
}, etime - cur);

위와 같이 실행 시 1을 출력,

종료 시 0을 출력하도록 한다.

시작 전
시작 및 종료

위와 같이 1과 0이

시작할 때, 종료할 때 정상적으로 출력된다.


오류 - 노드 안에서 시간설정

현재 오후 12:38 이므로

시작 시간을 12:39, 종료 시간을 12:40 로 설정한 후 테스트 해보았다.

 

하지만 오류발생

위와 같이 CLI 에 msg is not defined 라며 node-red를 강제 종료한다.

소스 코드에 msg를 전송하는 node.send(msg)에서 에러가 난 듯 하다.

setTimeout(function() {
	node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n실행됩니다.');
	msg.payload=1;
	node.send(msg);
}, sTimestamp - curTimestamp);

msg.payload=1 설정 후

node.send(msg) 하면 정상적으로 전송돼야 하는데

msg 선언 오류가 발생한다.

 

외부에서 시간을 입력할때는

node.send(msg)가 잘 동작했는데

노드 안에서 설정할 경우에는

오류가 발생한다.


수정 - 1

setTimeout(function() {
	node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n실행됩니다.');
	node.send(1);
}, sTimestamp - curTimestamp);

setTimeout(function() {
	node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n끝났습니다.'); 
	node.send(0);
}, eTimestamp - curTimestamp);

msg.payload=1, node.send(msg)를 

node.send(1); 로 수정해보았다.

이번에는 선언되지 않았다고 오류가 발생한다.

Node-red 서버가 종료되진 않는다.


수정 - 2 오류해결

https://nodered.org/docs/user-guide/messages

 

Working with messages : Node-RED

Working with messages A Node-RED flow works by passing messages between nodes. The messages are simple JavaScript objects that can have any set of properties. Messages usually have a payload property - this is the default property that most nodes will work

nodered.org

Node-red 에서 msg 를 출력하는 자료들을 찾아보았다.

위 링크에서 { } 형식으로 메시지를 출력하길래

맞춰서 수정해 보았다.

setTimeout(function() {
	node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n실행됩니다.');
	var msg = { payload:1 }
	node.send(msg);
}, sTimestamp - curTimestamp);

setTimeout(function() {
	node.warn("등록하신 스케쥴\n***********************\n시작 : "  + start + '\n종료 : ' + end + '\n***********************\n끝났습니다.'); 
	var msg = { payload:0 }
	node.send(msg);
}, eTimestamp - curTimestamp);

위와 같이 msg 를 생성하고 { } 안에 데이터를 담았다.

1이 출력되었다.

ㅠㅠㅠ 성공


외부에서 데이터를 입력할 때는

함수 자체에서 msg 를 사용하기 때문에

msg.payload 인자를 사용할 수 있었지만

 

노드 내부에서 시간을 설정할 때는 

msg.payload를 그대로 사용할 수 없기 때문에

{ } 에 담아서 출력해야 정상적으로 사용 가능하다.