Button State node - is something similar available for Dashboard 2?

Hi all,

I love to use the buttonstate node.
Now reworking some older projects this question came up: Is there a similar node available for the dashboard2?

Kind regards
Alexander

What have you installed that provides this node, I do not recognise the name.

I think the Button Group may do something like what you want, though exactly what the node you linked to does is not clear to me.

The idea behind this is the following:
a button can indicate what action is done when pressing like on or off
it can also display an error state, which means, on or off are not available
it can also display 'change in progress' indicating, that a motor is spinning up but not yet on full speed or such things.
The color of a button indicates a feedback.

I've seen a question about a toggle function here on the forum. I loaded the code example. I think, this can be expandet to my need, allows even more options for a button.
But i'm still open for hints!

I agree, and I think any update to original Dashboard should provide a greater level of functionality.

I think a good button node should be powerful but simple. To achieve this it would have modes:

  • Simple on-off switch (default mode)
  • Simple on-off momentary button
  • Multi-state switch

The simple on-off switch shows its state visually, with a sliding circle where left = off (and the colour is grey) and right = on (and the colour is highlighted e.g. green). It should also be possible to configure to replace the sliding circle (the switch visualisation) with a simple icon for on (with colour setting) and a simple icon for off (with colour setting).

Dashboard 2.0 does this. Although I have some criticisms because there's no validation on the icon field. This means if you make a mistake, it will default to a switch and you will have no understanding of why the icon isn't working.

However Dashboard 2.0 could very easily implement a multi-state switch by simply allowing you to create any number of your own states, and assigning icons and colours to those states.

As well, Dashboard 2.0 could provide the option for "text" by each icon in this case. Then it can handle multiple error states.

I don't know why this hasn't been considered but it would definitely be a great improvement.

When I build systems I tend to support multiple states. For example I have a water valve controller built from an Arduino. It has multiple local buttons for each water valve, and each one has an LED indicator in the button. When you press the button, it toggles the state of the water supply. But each toggle takes a certain amount of time to open or close the valve. So the LED shows the state of the valve normally, but also when you press the button, the LED flashes for 3 seconds to indicate that the valve is opening or closing, this provides feedback to the user so he knows the button press was correctly registered. This is really important when controlling certain devices which could be sensitive to change such as water supply for a whole building!

Personally I wish that the original Dashboard had been developed more actively to start to introduce multi-state buttons, button groups, etc. and so I'm glad to see Dashboard 2.0, although I have found the button node in Dashboard 2.0 is not perfect, the spacing is not logical on UI, and it lacks more advanced features like I've discussed above.

Button has four states. Normal, Hover, Down and Disabled. That's it.

To combine the button (event trigger) with the physical state of some kind of equipment there's noting special for button to have. It stands on logic you create or have and as every HTML element, the button can be presented with different colors and shapes and icons and.... the sky is limit.

How button does look like (represents different state of something) is matter of CSS. And that CSS can be applied and changed as you need. That all is built into dashboard 1 and 2. A lot of examples can be found how to do it.

This is an interesting concept and not one I'd considered. I'm quite interested because I'm thinking about button and switch designs at the moment.

A button component that has a built-in option for a temporary intermediate step which is either time-based as in your example or event driven, eg. after a click, it stays in the intermediate state until some external event moves it to the final state.

I suppose you would need to allow for a similar warm-down transition as well?

Such a button could be visualised either as a traditional button or as a "switch" I think. With the switch visualisation being a horizontal or vertical pill shape as you describe.

Are there other features you would want in such a button?

And note that I would keep this distinct as a button and not a multi-way switch which is something quite different. I think that would need a different definition.

I've just been building a web component that duplicates browser console log output to the web page. But an enhanced button might be an interesting next component to work on.

Using time based intermediate states with physical equipment may end with dead people. Really. You don't know how and where it will be used and even if you make red and bold warning, it is not enough. Buttons which represent physical state should never do anything else but being clickable when allowed and show the provided state. And for safety they also should be immedialtely disabled when clicked and wait for activation with new incoming state.

Good points. Though not all physical systems will actually have an electronic feedback. Such as the pump startup mentioned earlier. So there are valid times to use such a feature. It could also apply in a non-physical setup too where you might want a visible delay for some timing reason.

So the option should be available on the component.

If that somebody has safe system where to use such things, let them create what they want, but such things shold be avoided to become standards.

I did something similar when I had my flexdash dashboard, where the button status only changed when feedback had been received from the device.
It worked consistently well, but I now need to re-create in DB2.

I do a lot of Crestron / Extron programming. These are systems in the Audio/Video world, controllers and touchpanels that offer a gui to operate the system.

The most required functions are: (standard options, available on all systems)

  • text and text-color
  • button color
  • icon
  • states - which is a combination of the above

very helpful but not very often used function

  • visibility

Lets assume a security center, one can route a video stream to the main display. There might be situations, where a change of the routing must be inhibited. In these cases i use the visibility option, the button disappears. When the situation allows new routings, the button will reappear.

Feedbacks:
The visual implementation is the states-option.

Timed feedbacks: a mess. Let's assume the runtime of blinds. Shure, one can take a stopwatch and use the time he measured. But will that time be correct after 2 years, will it be the same in summer and in winter?
And what happens after a power outage? Will a timed feedback be adequate?
In almost all cases i use a true feedback or no feedback.
If an action triggert by pressing a button happens within one or two seconds, no special feedback is required.
Lets assume you turn on a video-projector. Not a new one with a laser-lightsource, but one with a bulb. It takes about 30 seconds to reach full brightness. And after turning it off, you need to wait 2 to 3 minutes before you can turn it on again. These situations need a correct feedback like warming or cooling. Usually you need to parse the feedback from the projector.

A special goodie is a transparency option. Lets assume you have some transport buttons inserted in a video. After 10 seconds or so you want them to disappear. Just turning them off is flintstone manner, fading them out is state of the art.

FYI, completely agree with everyone that timed states are a bad idea as a general rule.

My example was for a hardware valve controller and the flashing LED (for 2 seconds) was only for aesthetic / fun purposes and to act as a reminder to the user that it’s not instant. And also as additional button feedback. In actual fact it is possible to interrupt closing the valve during its closing process, and the valve just starts opening again.

There are times when timers are useful as button states, but agree not for control of physical devices. The only scenario they are acceptable should be … for timer displays! (Eg flash for two seconds to tell the user that two seconds have elapsed.)

By the way, to @hotNipi re my post above. I was really referring to switch nodes, with sliding on-off switches. Not buttons. I think other people use the word “button” in a very HTML/CSS way. For me a button is anything you press. But in NodeRed I know there is a difference between button and switch. Sorry I didn’t make it clear I was referring to button.

Vuetfy provides pretty fancy way to make safe button , if anybody interested

[{"id":"2e8dd42000976284","type":"ui-template","z":"fcc7b2a2fdda30d4","group":"0c6ef72c4538c515","page":"","ui":"","name":"button waits input to activate after click","order":1,"width":0,"height":0,"head":"","format":"<template>\n    <v-btn :loading=\"loading\" class=\"flex-grow-1\" height=\"48\" variant=\"tonal\" @click=\"setStateAndSend()\">\n        GARDEN LIGHTS\n    </v-btn>\n</template>\n\n<script>\n    export default {\n        data() {\n            // define variables available component-wide\n            // (in <template> and component functions)\n            return {\n                loading: false,\n            }\n        },\n        watch: {\n            // watch for any changes of \"count\"\n            msg: function () {\n                if(this.msg?.payload != undefined){\n                    this.loading = false\n                }\n            }\n        },\n        computed: {\n            \n           \n        },\n        methods: {\n            // expose a method to our <template> and Vue Application\n            setStateAndSend: function () {\n                this.loading = true\n                this.send({payload:\"clicked\"})\n            }\n        },\n        mounted() {\n            \n        },\n        unmounted() {\n           \n        }\n    }\n</script>\n<style>\n   \n</style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":310,"y":260,"wires":[["7c9d5f81fe1c2292"]]},{"id":"7c9d5f81fe1c2292","type":"trigger","z":"fcc7b2a2fdda30d4","name":"pretending that switching takes time","op1":"","op2":"true","op1type":"nul","op2type":"bool","duration":"2","extend":true,"overrideDelay":false,"units":"s","reset":"","bytopic":"all","topic":"topic","outputs":1,"x":720,"y":260,"wires":[["2e8dd42000976284"]]},{"id":"c0d265098e4ad9cb","type":"comment","z":"fcc7b2a2fdda30d4","name":"actual implementation should never loop back this way","info":"","x":540,"y":320,"wires":[]},{"id":"0c6ef72c4538c515","type":"ui-group","name":"Group Name","page":"4be3167f72364b22","width":"6","height":"1","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false"},{"id":"4be3167f72364b22","type":"ui-page","name":"test-page","ui":"f6017d9b9437205e","path":"/test-page","icon":"home","layout":"grid","theme":"fbca0ce017dca174","order":1,"className":"","visible":"true","disabled":"false"},{"id":"f6017d9b9437205e","type":"ui-base","name":"My Dashboard","path":"/dashboard","includeClientData":true,"acceptsClientConfig":["ui-notification","ui-control"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"default","titleBarStyle":"default"},{"id":"fbca0ce017dca174","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#0094CE","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]
1 Like

That's just CSS. Transparency/visibility is standard, nothing really special need for that.

The current ui-switch does go some way down this road with the 'Show State of Input` mode, which is available when Passthrough is disabled. In this mode clicking the switch sends the message and shows a waiting icon, waiting for a message to be received telling it what to show.

This could be a first step

[
    {
        "id": "cdc19dcf50907703",
        "type": "ui-button",
        "z": "99366da2301717ce",
        "group": "d2ada84cc7beaf41",
        "name": "",
        "label": "btn1",
        "order": 5,
        "width": "1",
        "height": "1",
        "emulateClick": false,
        "tooltip": "",
        "color": "",
        "bgcolor": "",
        "className": "",
        "icon": "",
        "iconPosition": "left",
        "payload": "",
        "payloadType": "str",
        "topic": "topic",
        "topicType": "msg",
        "buttonColor": "green",
        "textColor": "white",
        "iconColor": "",
        "x": 910,
        "y": 380,
        "wires": [
            [
                "6dc00fa6b87a959c"
            ]
        ]
    },
    {
        "id": "d363987354b7c11e",
        "type": "debug",
        "z": "99366da2301717ce",
        "name": "debug 2",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 880,
        "y": 340,
        "wires": []
    },
    {
        "id": "4b007b52ceaa2b7d",
        "type": "inject",
        "z": "99366da2301717ce",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "btn",
        "payload": "grey",
        "payloadType": "str",
        "x": 480,
        "y": 320,
        "wires": [
            [
                "8da43418d62cac46"
            ]
        ]
    },
    {
        "id": "cc30c8ae72af2e01",
        "type": "inject",
        "z": "99366da2301717ce",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "btn",
        "payload": "green",
        "payloadType": "str",
        "x": 480,
        "y": 360,
        "wires": [
            [
                "8da43418d62cac46"
            ]
        ]
    },
    {
        "id": "8da43418d62cac46",
        "type": "function",
        "z": "99366da2301717ce",
        "name": "btn setup",
        "func": "var top = msg.topic;\nvar val = msg.payload;\nvar msg1 = {};\nvar ui_update = {};\nvar bc = context.get(\"bc\") || \"grey\";\nvar tc = context.get(\"tc\") || \"white\";\nvar lb = context.get(\"lb\") || \"btn1\";\n\nif (top === \"btn\") bc = val;\nif (top === \"txt\") tc = val;\nif (top === \"lab\") lb = val;\n\ncontext.set(\"bc\",bc);\ncontext.set(\"tc\",tc);\ncontext.set(\"lb\",lb);\n\nmsg1 = {\n    payload: \"\",\n    ui_update: {\n        buttonColor: bc,\n        textColor: tc,\n        label: lb,\n    },\n}\n\nreturn msg1;",
        "outputs": 1,
        "timeout": 0,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 700,
        "y": 380,
        "wires": [
            [
                "cdc19dcf50907703",
                "d363987354b7c11e"
            ]
        ]
    },
    {
        "id": "e66a5e736d15ab21",
        "type": "inject",
        "z": "99366da2301717ce",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "lab",
        "payload": "Btn1",
        "payloadType": "str",
        "x": 480,
        "y": 400,
        "wires": [
            [
                "8da43418d62cac46"
            ]
        ]
    },
    {
        "id": "7b00ba7e3a4fa7f4",
        "type": "inject",
        "z": "99366da2301717ce",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "lab",
        "payload": "Btn2",
        "payloadType": "str",
        "x": 480,
        "y": 440,
        "wires": [
            [
                "8da43418d62cac46"
            ]
        ]
    },
    {
        "id": "d2ada84cc7beaf41",
        "type": "ui-group",
        "name": "g1",
        "page": "a753d3c3ec5c9991",
        "width": "6",
        "height": "1",
        "order": -1,
        "showTitle": true,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "a753d3c3ec5c9991",
        "type": "ui-page",
        "name": "p1",
        "ui": "fdd5060deaa38d04",
        "path": "/page1",
        "icon": "home",
        "layout": "grid",
        "theme": "ea314d4cabcf2177",
        "order": -1,
        "className": "",
        "visible": "true",
        "disabled": "false"
    },
    {
        "id": "fdd5060deaa38d04",
        "type": "ui-base",
        "name": "UI Name",
        "path": "/dashboard",
        "includeClientData": true,
        "acceptsClientConfig": [
            "ui-notification",
            "ui-control"
        ],
        "showPathInSidebar": false,
        "showPageTitle": true,
        "navigationStyle": "default",
        "titleBarStyle": "default"
    },
    {
        "id": "ea314d4cabcf2177",
        "type": "ui-theme",
        "name": "Default Theme",
        "colors": {
            "surface": "#ffffff",
            "primary": "#0094CE",
            "bgPage": "#eeeeee",
            "groupBg": "#ffffff",
            "groupOutline": "#cccccc"
        },
        "sizes": {
            "pagePadding": "12px",
            "groupGap": "12px",
            "groupBorderRadius": "4px",
            "widgetGap": "12px",
            "density": "default"
        }
    }
]

We've not had anyone requesting it. Given that you are. Feature Requests are most appreciated.

I've not had a lot of time today but I have knocked up a proof-of-concept multi-way-swich web component if anyone is interested. Just let me know, I'll share in a different thread.

Doesn't look very pretty at the moment but I've a list of improvements to do when I get time.

image

This shows 3 switches, each using a different mode: button, slider, knob.