Is there a way to have a dropdown helper populate the options from a text file or a google sheet? I’m looking for a user friendly way to add options to dropdowns, a viable alternative would be to be able to type into a text helper and append that input to the options of the dropdown, thanks!
Setting it up based on a Input Text helper would be a lot easier, but the other two are also possible, probably…
If you look at the third automation example, it adds a select option through mqtt.
https://www.home-assistant.io/integrations/input_select/#automation-examples
so I made some progress with Node Red, I made a text file and have node red read it and turn each line into a message, then I pass that on to a action node with input_select.set_options, and it ALMOST works, the issue i’m having is that instead of aggregating to the set of options, it replaces the existing options with the one being fed into it, so by the end, the only option in the input_select is the last item in the text file.
Some research and I found this:
{{ state_attr('input_select.test', 'options') + ['Person C']}}
I just have no idea how to format the node red data like that, I keep getting formatting errors, here’s the JSON for the node red flow:
[
{
"id": "b73d1acb0c124c13",
"type": "tab",
"label": "Flow 1",
"disabled": false,
"info": "",
"env": []
},
{
"id": "6924af1699245077",
"type": "inject",
"z": "b73d1acb0c124c13",
"name": "",
"props": [
{
"p": "payload"
},
{
"p": "topic",
"vt": "str"
}
],
"repeat": "",
"crontab": "",
"once": false,
"onceDelay": 0.1,
"topic": "",
"payload": "",
"payloadType": "date",
"x": 140,
"y": 200,
"wires": [
[
"e61ccabf1a407d53"
]
]
},
{
"id": "5cd22fc0dcced60c",
"type": "api-call-service",
"z": "b73d1acb0c124c13",
"name": "set Input_select options",
"server": "b6b1b1d7.8602b",
"version": 7,
"debugenabled": true,
"action": "input_select.set_options",
"floorId": [],
"areaId": [],
"deviceId": [],
"entityId": [
"input_select.tryout"
],
"labelId": [],
"data": "{ \"options\": \"{{payload}}\"}",
"dataType": "json",
"mergeContext": "",
"mustacheAltTags": false,
"outputProperties": [],
"queue": "none",
"blockInputOverrides": true,
"domain": "input_select",
"service": "set_options",
"x": 650,
"y": 200,
"wires": [
[
"127cc2e416b86ff0"
]
],
"info": "works with single line"
},
{
"id": "127cc2e416b86ff0",
"type": "debug",
"z": "b73d1acb0c124c13",
"name": "debug 2",
"active": true,
"tosidebar": true,
"console": false,
"tostatus": false,
"complete": "false",
"statusVal": "",
"statusType": "auto",
"x": 860,
"y": 200,
"wires": []
},
{
"id": "e61ccabf1a407d53",
"type": "file in",
"z": "b73d1acb0c124c13",
"name": "",
"filename": "/homeassistant/menu.text",
"filenameType": "str",
"format": "lines",
"chunk": false,
"sendError": false,
"encoding": "none",
"allProps": false,
"x": 370,
"y": 200,
"wires": [
[
"5cd22fc0dcced60c"
]
]
},
{
"id": "b6b1b1d7.8602b",
"type": "server",
"name": "Home Assistant",
"addon": true
}
]
This is all coming back to me, there is another problem, upon restart all options will reset to the default and changes are lost. It’s easier, at least for me, to do this all in nodered.
Create a select in NR. Enable global context storage by clicking any HA node and editing the server, check the box for global context store if it is not checked already. You need to next go to the addon_config
folder, same location as /media
, look for the NR folder.
Inside you will find a file settings.js. Find the global context entry and change it to
contextStorage: {
default: "file",
memoryOnly: { module: 'memory' },
file: { module: 'localfilesystem' }
},
Then restart NR. This will allow storage that persists through restarts. You’ll need to add an mqtt automation in HA and use that to tell NR that HA restarted and to reload the options.
alias: ha just restarted
description: HA just restarted
triggers:
- event_type: homeassistant_started
trigger: event
- event: start
trigger: homeassistant
conditions: []
actions:
- metadata: {}
data:
qos: "1"
topic: myha
payload: "on"
action: mqtt.publish
mode: single
The first inject shows an array of options to add. The second inject fires when nodered starts. The mqtt node fires when HA restarts.
[{"id":"bee2d04acc72b3dd","type":"ha-update-config","z":"d4b982ad2e73341f","name":"","server":"6b1110b5.183a4","entityConfig":"9f1b29f91da6369f","version":0,"outputProperties":[],"x":660,"y":4000,"wires":[[]]},{"id":"9a204eb5061e61ac","type":"function","z":"d4b982ad2e73341f","name":"function 1","func":"let addOptions = msg.payload;\nlet exOptions = global.get('homeassistant.homeAssistant.states[\"select.test_select\"].attributes.options');\nmsg = {};\nlet nextOptions = { \"options\": exOptions.concat(addOptions) };\nglobal.set(\"nextOptions\", nextOptions);\nmsg.payload = nextOptions;\nreturn msg;","outputs":1,"timeout":0,"noerr":0,"initialize":"","finalize":"","libs":[],"x":420,"y":3940,"wires":[["bee2d04acc72b3dd"]]},{"id":"91594031d514f3e4","type":"inject","z":"d4b982ad2e73341f","name":"add options","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[\"4\", \"5\", \"6\"]","payloadType":"json","x":230,"y":3940,"wires":[["9a204eb5061e61ac"]]},{"id":"0fdafcb994a1caf2","type":"inject","z":"d4b982ad2e73341f","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payload":"nextOptions","payloadType":"global","x":250,"y":4000,"wires":[["bee2d04acc72b3dd"]]},{"id":"08af10390214c0b4","type":"mqtt in","z":"d4b982ad2e73341f","name":"home assistant start","topic":"/myha","qos":"2","datatype":"auto-detect","broker":"601bef1.d5b981","nl":false,"rap":true,"rh":0,"inputs":0,"x":250,"y":4060,"wires":[["92c69a72fd195fef"]]},{"id":"92c69a72fd195fef","type":"change","z":"d4b982ad2e73341f","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"nextOptions","tot":"global"}],"action":"","property":"","from":"","to":"","reg":false,"x":440,"y":4060,"wires":[["bee2d04acc72b3dd"]]},{"id":"6b1110b5.183a4","type":"server","name":"Home Assistant","version":5,"addon":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true,"heartbeat":false,"heartbeatInterval":"30","areaSelector":"friendlyName","deviceSelector":"friendlyName","entitySelector":"id","statusSeparator":"at: ","statusYear":"hidden","statusMonth":"short","statusDay":"numeric","statusHourCycle":"h23","statusTimeFormat":"h:m","enableGlobalContextStore":true},{"id":"9f1b29f91da6369f","type":"ha-entity-config","server":"6b1110b5.183a4","deviceConfig":"","name":"test select","version":6,"entityType":"select","haConfig":[{"property":"name","value":"test select"},{"property":"icon","value":""},{"property":"entity_picture","value":""},{"property":"entity_category","value":""},{"property":"options","value":["option1","option2","option3"]}],"resend":false,"debugEnabled":false},{"id":"601bef1.d5b981","type":"mqtt-broker","name":"Mosquitto","broker":"127.0.0.1","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":4,"keepalive":"60","cleansession":true,"autoUnsubscribe":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"userProps":"","sessionExpiry":""}]
Yeah, ironically that’s the easy part, I’m stuck on the original issue…. Gonna walk away from it for a while
The flow I supplied takes into account that the original options are lost. The function, gets the existing options for the select and adds the new options to it. Then updates the select entity with the new and existing options.
// get new options array from msg.payload
let addOptions = msg.payload;
//get existing options for select
let exOptions = global.get('homeassistant.homeAssistant.states["select.test_select"].attributes.options');
// join old and new options
let nextOptions = { "options": exOptions.concat(addOptions) };
//store options to be update on restarts
global.set("nextOptions", nextOptions);
// clear existing message
msg = {};
//send new array to select
msg.payload = nextOptions;
return msg;
Edit: I am going to move this to nodered. If you can post an example of a the text file, I’ll help you get it into the function in the proper format.
If you read in a text file, as one message per line, for a file of 3 lines you get 3 messages, one after the other.
Each message in Node-RED is independent, so each message goes through to the Action call and updates the Option Set List to that single option, one after the other. At the end, you will just have the last option only.
What you probably want to do is capture all lines into an array, and then pass that single array with all the options. Just add a Join node, set to manually create an array with a timeout.
Works for me.
man, I got more answer than I hope for, I’ll give them a shot when I get a minute, this week is crazy with work and I gotta pay for all this crap!
thanks for all the help, you guys are awesome!!