Button block until 2 seconds passes

Hello, I got flow that control relays via modbusRTU. When I click the button on node-red dashboard to turn on the relay I got to wait at least 2 seconds to turn off the relay or turn on the others because MODBUS serial is busy. Is it possible to block button until 2 seconds passes?

Yes. There are many ways. Using built in core nodes, you could use a change node to set a flow or global flag that then blocks further messages. Add a trigger node to send nothing then send a reset 2 seconds later.

Why is it busy? Many reads? or many writes?

Are you reading lots of single items?

Many writing request. Sending message via MQTT to my esp8266 then modbus command to modbus relay board.
When I press1 (relay1) button on node-red and then after 1second I want it to turn off it doesn;t turn off

The only one note: ModbusRTU write register operation takes time. That is you can get next MQTT event before previous write operation has finished in that case mb.writeHreg will not perform write request as serial but is busy.

Have you put anything in to turn it off?

Have you looked at the trigger node?

1 Like

Each click I got to wait at least 2 seconds then everything works. But I fast click switches on node-red dashboard it doesn't change the state of the relay. So you suggest trigger node. I got to look it up.

void callback(char * topic, byte * payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  if (!mb.slave()) {
    if (strstr(topic, sub1)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the LED if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0001, 0x0100, cbWrite); // 0x001 - relay 1, 0x002 - relay 2 and so on 

        // 0x0100 - turn on relay, 0x0200 turn off relay 

      } else {

        mb.writeHreg(SLAVE_ID, 0x0001, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub2)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0002, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0002, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub3)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0003, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0003, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub4)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0004, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0004, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub5)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0005, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0005, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub6)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0006, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0006, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub7)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0007, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0007, 0x0200, cbWrite); // turn off the light

      }
    } else if (strstr(topic, sub8)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the light if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0008, 0x0100, cbWrite);

      } else {

        mb.writeHreg(SLAVE_ID, 0x0008, 0x0200, cbWrite); // turn off the light

      }
    } else {
      Serial.println("unsubscribed topic");
    }
  }
}


So I can use trigger node and set it to wait for 2 seconds and this will do the trick?

trigger node doesn't do the trick :smiley: or I don't know how to manage it. I'm such a rookie with HA and node-red. Could you please create a flow for me? I can't find an example how to manage it. Gotta search longer..

As a new user, I recommend watching this playlist: Node-RED Essentials. The videos are done by the developers of node-red. They're nice & short and to the point. You will understand a whole lot more in about 1 hour. A small investment for a lot of gain.


VI6TmDa06d

[{"id":"ade7ead4d31c06dc","type":"inject","z":"af952aeaa20f4f97","name":"dashboard button","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"1","payloadType":"str","x":1720,"y":500,"wires":[["1c9b78d02ca6b8fd"]]},{"id":"1c9b78d02ca6b8fd","type":"trigger","z":"af952aeaa20f4f97","name":"","op1":"1","op2":"0","op1type":"str","op2type":"str","duration":"2","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":1910,"y":500,"wires":[["72105917ed0f0a29"]]},{"id":"72105917ed0f0a29","type":"debug","z":"af952aeaa20f4f97","name":"To MQTT","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","statusVal":"","statusType":"auto","x":2070,"y":500,"wires":[]}]

NOTE: i am unsure what you actual use case is.

The above is based on your earlier statement of switching off after 2 sec.

If you need something else, please be 100% specific.

Sometimes to be fail safe with user interactions, self disabling/enabling the buttons may come handy.

Heres one way:

[
    {
        "id": "9ee2ddd772eacc28",
        "type": "ui_button",
        "z": "e490bfdba10fb48a",
        "name": "",
        "group": "922cc2b20a87f647",
        "order": 4,
        "width": 0,
        "height": 0,
        "passthru": false,
        "label": "self activating button",
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "payload": "",
        "payloadType": "date",
        "topic": "topic",
        "topicType": "msg",
        "x": 640,
        "y": 520,
        "wires": [
            [
                "7849fdaecc168864"
            ]
        ]
    },
    {
        "id": "7849fdaecc168864",
        "type": "function",
        "z": "e490bfdba10fb48a",
        "name": "",
        "func": "\nlet msg_1 = {payload:\"ON\",topic:\"something\"} // or OFF, make your own logic.\nlet msg_2 = {enabled:false}\nreturn [msg_1,msg_2]\n",
        "outputs": 2,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 830,
        "y": 520,
        "wires": [
            [
                "7deb64b7e76f4fb3"
            ],
            [
                "a84dd3e194c2cbde"
            ]
        ]
    },
    {
        "id": "7deb64b7e76f4fb3",
        "type": "link out",
        "z": "e490bfdba10fb48a",
        "name": "to-device",
        "links": [],
        "x": 945,
        "y": 490,
        "wires": []
    },
    {
        "id": "a84dd3e194c2cbde",
        "type": "link out",
        "z": "e490bfdba10fb48a",
        "name": "back-to-button",
        "links": [
            "7da64e819336c26a"
        ],
        "x": 945,
        "y": 550,
        "wires": []
    },
    {
        "id": "7da64e819336c26a",
        "type": "link in",
        "z": "e490bfdba10fb48a",
        "name": "to-button",
        "links": [
            "a84dd3e194c2cbde"
        ],
        "x": 195,
        "y": 560,
        "wires": [
            [
                "7e8fb52f4cb3ff24"
            ]
        ]
    },
    {
        "id": "7e8fb52f4cb3ff24",
        "type": "trigger",
        "z": "e490bfdba10fb48a",
        "name": "",
        "op1": "",
        "op2": "{\"enabled\":true}",
        "op1type": "pay",
        "op2type": "json",
        "duration": "1",
        "extend": false,
        "overrideDelay": false,
        "units": "s",
        "reset": "",
        "bytopic": "all",
        "topic": "topic",
        "outputs": 1,
        "x": 290,
        "y": 520,
        "wires": [
            [
                "f24a7e4b1d9747ad"
            ]
        ]
    },
    {
        "id": "f24a7e4b1d9747ad",
        "type": "change",
        "z": "e490bfdba10fb48a",
        "name": "",
        "rules": [
            {
                "t": "move",
                "p": "payload.enabled",
                "pt": "msg",
                "to": "enabled",
                "tot": "msg"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 440,
        "y": 580,
        "wires": [
            [
                "9ee2ddd772eacc28"
            ]
        ]
    },
    {
        "id": "922cc2b20a87f647",
        "type": "ui_group",
        "name": "Default",
        "tab": "b15d581341d0093f",
        "order": 1,
        "disp": true,
        "width": "6",
        "collapse": false,
        "className": ""
    },
    {
        "id": "b15d581341d0093f",
        "type": "ui_tab",
        "name": "Home",
        "icon": "dashboard",
        "disabled": false,
        "hidden": false
    }
]

Or this will disable the switch for 2 seconds after you toggle it

[{"id":"accb4fab15dd9765","type":"ui_switch","z":"33c0f0bf5f175742","name":"","label":"switch","tooltip":"","group":"3ce32370.c60f1c","order":3,"width":0,"height":0,"passthru":false,"decouple":"false","topic":"topic","topicType":"msg","style":"","onvalue":"true","onvalueType":"bool","onicon":"","oncolor":"","offvalue":"false","offvalueType":"bool","officon":"","offcolor":"","animate":false,"className":"","x":270,"y":380,"wires":[["4bc694a366f31a8e","7ca1966b42dabdaa"]]},{"id":"7ca1966b42dabdaa","type":"debug","z":"33c0f0bf5f175742","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":570,"y":380,"wires":[]},{"id":"4bc694a366f31a8e","type":"trigger","z":"33c0f0bf5f175742","name":"disable for 2s","op1":"false","op2":"true","op1type":"bool","op2type":"bool","duration":"2","extend":false,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":190,"y":320,"wires":[["b9aecf287f15b1a6"]]},{"id":"b9aecf287f15b1a6","type":"change","z":"33c0f0bf5f175742","name":"","rules":[{"t":"set","p":"enabled","pt":"msg","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":360,"y":320,"wires":[["accb4fab15dd9765"]]},{"id":"3ce32370.c60f1c","type":"ui_group","name":"Demo","tab":"d74bbed4.c2cfb","order":2,"disp":false,"width":"6","collapse":false,"className":""},{"id":"d74bbed4.c2cfb","type":"ui_tab","name":"Demo","icon":"dashboard","order":4,"disabled":false,"hidden":false}]

Watch this you will understand: MODBUS Serial is busy - YouTube
if there is too much MODBUS writing request it doesn't change the state of the relay.
Got to do: delay() each write?

void callback(char * topic, byte * payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  if (!mb.slave()) {
    if (strstr(topic, sub1)) {
      for (int i = 0; i < length; i++) {
        Serial.print((char) payload[i]);
      }
      Serial.println();
      // Switch on the LED if an 1 was received as first character
      if ((char) payload[0] == '1') {

        mb.writeHreg(SLAVE_ID, 0x0001, 0x0100, cbWrite);
       delay(2500);
      } else {

        mb.writeHreg(SLAVE_ID, 0x0001, 0x0200, cbWrite); // turn off the light
        delay(2500)

      }

The issue you show in the youtube video looks like its due to the 2.5s delay - that will be blocking.

Also, as the ESP is single threaded - I believe you dont need a delay after the Serial.print command (or at most, 30ms will do)

At first I didn't have this delay (on the video it is without the delay and when I press fast to turn on switch 1 and 2 it doesnt :D) see: Modbus - fast clicking switches - YouTube

You will need to debug your auruino code (using serial printing) - confirm your values ACTUALLY get to mb.writeHreg function (e.g. are they getting blocked by if (!mb.slave()) { ? Are they not arriving in the MQTT callback function?

Also, are you certain the value is NOT being written to the relay? It may be that the fast operation of your switches are too fast to register - only logging will confirm this.

I would probably use a positive feedback by using cbWrite to send the result to your flow via MQTT - then use that to animate the button position.

Yup: got commands to read the channel state: 8 Channel Rail RS485 Relay commamd.docx - Google Docs
I gotta figure sth out ;/

Sorry for that late reply. What nodes would you use to animate tbe button position?
mqtt in node to get the feedback from the modbus relay and send it via mqtt by esp 8266.
Right now I got Home Assistant with entity node connected with mqtt out to publish the payload 1 or 0 to esp with my relay board.


in payload section I got something to change?
What would like an example with animation button?

Wouldn't a simple delay node in rate limit setting solve the issue? You can toggle as much as you want, the messages will get queued up and be send with a 2s delay.

I managed to fix it, but I'm now struggling with animating the buttons depend on the relay state. I got to send the data from my esp to my node-red flow with mqtt in node then convert it to json and then what... ;/?

image
Just for test, they are not in queue e.g. when I click 1 button and then second one to turn on and it doesn't turn on :smiley: or I hasn't clicked the proper option/ connect it properly

hi there, how did you connect from esp to modbus ?