Hi Alan.? That's quite a catch.? I never would have thought of that.? Thanks for the nice little flow that can fix my images.? I've tried a few with moderate success but now it's just a matter of becoming more familiar with the SVG properties.? Thanks once again to you and all the others who have been patient and very helpful.? Ken, K2KXK
I have been away from node-red since 2020.? Back then, I was using the VITA49 and Flex Radio V6 flows that Dave shared,
on a RPi 3B+. ?? I have that all working again as of yesterday. ? ? (I used to be N6YFM, now AB6G since Aug 2024)
?
Now, I just googled and found a few threads where it looks like most people have dumped the above flows, and are now using FRStack API and DotNET. ?? Is this a better way to go?
?
QUESTION:?? I found superficial hints that the RPi3 was no longer good enough for all this, since it only has 1GB of RAM.
It looks like most people are now running this on a RPi4 with the 4GB RAM model being appropriate??? Is this information correct?? Should I move to an RPi4 with 4GB ram?
?
Also, to aid my learning in the transition, where can I find the most recent version of the Flex Radio 6600 flows that use FRStack API and DotNet?
?
Sincere Thanks,
?
Neal
Advice for building a new Node Red RPi-3B+ in 2025
I have several idle RPi 3B+ units.? But they have only 1 GB of RAM.
My old 2020 RPi3 node-red unit ran just fine with 32bit OS and 32bit .net install.
If I build a new fresh install with Pi OS bookworm right now, I assume I should still use the 32bit OS, since it is an RPi 3 B+ with only 1GB of ram.
But on this Group's Wiki, the notes for installing .Net aspcore 8.0.13 (latest as of 2/13/25) and FRStack WebAPI 3.8.12.78 (latest as of 2/13/25)
only talk about the 64bit versions.
?
Does this group know the download locations for the 32bit versions of .net and FRStack API,? or in 2025, do you feel that I should no longer use the Raspberry Pi3, and instead buy a Pi4 with 4GB and install everything in 64bit?
I wanted to try to use the Pi3, since most of the time, the CPU utilization never went above 40%.
You cannot have strings?within strings. ? SVG uses "SVG code" in its code, but node-red sees this as a sting......
Other than the opening and closing "" for the code, because the full code is a string, there can be no strings between them. ? Again, no stings?withi?strings. ? ?Node Red sees them as ""svg code""
To fix this, add a reverse \ in front of the SVG " to show it is a special character.
ie. " \" svg code \" "
It can be a pain finding all the " in a long SVG string, so I built a flow to do the conversion. ?the flow is attached.
Paste your SVG code into the inject button as a string.? Often the debug is limited in length and is too small to show you the full?converted line, so I use a "write file" node to create a text file to your computer. ? In this node, be sure to adjust the path to the desired directory on your device running node-red.
The change node does a simple find and replace action, find each " and replace with \".
On Wed, Mar 12, 2025 at 1:34?PM Ken Kayser via <kxkayser=[email protected]> wrote:
Hi Alan.? I think I am getting the concepts.? My issue right now is finding a way to format the svg data.? I have tried several editors and converters but can't get a clean svg image or at least one where the NR function editor doesn't complain.? I have attached a flow with a few example nodes.? Ex. 1 is extracted from your Switch image and works fine.? It displays the switch graphic along with my tetx and I can even change the graphics color.? Ex. 2 is from a conversion.? It has 2 path attributes which the editor doesn't seem to like.? Even if I remove the 2nd one, it still has tons of syntax errors..? Ex. 3 is my attempt at a base64 version.? It's syntax is OK but when inserted into the flow, it doesn't display any image.? Hopefully, you can easily spot the problems and get me on the right road.? I hate to have come this far and have simple syntax trip me up.? Thanks as always for your time and expertise.
Hi Alan.? I think I am getting the concepts.? My issue right now is finding a way to format the svg data.? I have tried several editors and converters but can't get a clean svg image or at least one where the NR function editor doesn't complain.? I have attached a flow with a few example nodes.? Ex. 1 is extracted from your Switch image and works fine.? It displays the switch graphic along with my tetx and I can even change the graphics color.? Ex. 2 is from a conversion.? It has 2 path attributes which the editor doesn't seem to like.? Even if I remove the 2nd one, it still has tons of syntax errors..? Ex. 3 is my attempt at a base64 version.? It's syntax is OK but when inserted into the flow, it doesn't display any image.? Hopefully, you can easily spot the problems and get me on the right road.? I hate to have come this far and have simple syntax trip me up.? Thanks as always for your time and expertise.
Definitely do a backup by exporting all flows on a regular basis. SD cards can fail without notice. And while we are on the subject¡
If you rather do a clean install instead of upgrading an old OS version, the WiKi has been updated for the 64 bit Pi OS install. Use a new SD card. Raspberry Pi 3 and 4 units can use a USB to NVME portable housing. ?The NVME can handle a higher read/write lifetime although I will state I personally never had an SD failure using the generic Micro Center branded cards.?
?I upgraded to an Pi 5 and boot from an NVME drive, which can handle higher read/write lifetime and will run faster. Raspberry Pi 3 and 4 can use a NVME to USB case while the new Pi 5 supports PCIe 3.0. The case I use has a heatsinked mount for the NVME drive and ribbon cable to connect to the PCIe connector on the Pi5. It was recommended by another member on this group.?
On Mar 11, 2025, at 9:56?PM, Neal AB6G via groups.io <nealix@...> wrote:
?
Thanks for the tips!
73,
Neal
On Tue, Mar 11, 2025 at 6:44?PM Kyle AA0Z via <kylekrieg=[email protected]> wrote:
Hey Neal,
?
You should be good to complete a full upgrade on your Pi.??
?
Backup your flow to another machine before you start your upgrade.? I would also re-run the Node Red installer to make sure you are fully up to date on Node Red.? Then upgrade all your nodes to the latest by the pallet manager.
?
Good luck in your upgrades!
?
Kyle
AA0Z
?
?
New to NodeRed - Looking for help to jump start configuring for our club's Flex 6400
Can anyone share the scripts that a ham radio club uses to give access to club members to a Flex6400 radio? We currently use a VPN and it works BUT users are presented witth the standard SmartSDR. I saw several examples of custom UIs that only give usess access to functions the club let's them use.
?
I for one wants to learn how to use Node Red but to do so, I need a jump start. If you can share scropts, we can use them for our club and I will then work with others to learn how to customize them, and share back. It's like how I learned how to configure code plugs for DMR and P25 ... I started wth functional code plugs, then learned how to build them
Re: Question: Does RPi OS upgrade break node-red flows?
On Tue, Mar 11, 2025 at 6:44?PM Kyle AA0Z via <kylekrieg=[email protected]> wrote:
Hey Neal,
?
You should be good to complete a full upgrade on your Pi.??
?
Backup your flow to another machine before you start your upgrade.? I would also re-run the Node Red installer to make sure you are fully up to date on Node Red.? Then upgrade all your nodes to the latest by the pallet manager.
?
Good luck in your upgrades!
?
Kyle
AA0Z
?
?
Re: Question: Does RPi OS upgrade break node-red flows?
You should be good to complete a full upgrade on your Pi.??
?
Backup your flow to another machine before you start your upgrade.? I would also re-run the Node Red installer to make sure you are fully up to date on Node Red.? Then upgrade all your nodes to the latest by the pallet manager.
On Tue, Mar 11, 2025 at 12:53 PM, Ken Kayser wrote:
antenna graphic and had a .png file, how would I create the code to include in the build node??
Ken
?
A easy way to start creating SVG code, is to use any of the popular graphic applications. ?Expoet the file as a SVG formatted file. ?This will be the code to use in the various node Red functions. ?that is how I built the meter SVG.?
?
?
You can also, embed an image file within SVG Code. ? Select in image, use an online tool to convert it to base 64. ?Put his into a fiction with msg.image = base 64 image code here. ?Put this upstream of my sag functions, in the SVG build like, add the image and you will now see he image in the button. ?The order of elements in the SVG code sets the layers, top to bottom, so put the image at the end of the SVG code.
?
?
?
Again, build a function where msg.image is the base64 code of the desired image, put this upstream of the "build StreamDeck Button" function. ? Add a variable to the line 35 SVG code, image as below. ?This will put the Image in the SGV background.
You can also use common SVG element codes, like a line or triangle shapes. ? ?The rotor graphic uses math to allowing moving the shape a coordinates of the shape, ie the one and the triangle shapes. ? Its all X/U coordinates in pixels to create the shapes, with a little trigonometry to move the stuff around in a circle.
Hey Warren.? I had no idea i could have the context "persist" across startups.? That's a great technique and I'll set it up.? I also see how Alan is building the graphics nodes although I have to think through the "contextR1" logic each time - I'm sure it will be clearer as I work with it.? I am still uncertain about how he comes up with the strings that actually make up the image that represents an actual graphic.? For example, if I wanted an antenna graphic and had a .png file, how would I create the code to include in the build node?? That's the piece I seem to be missing at the moment but I'm confident that you or one of the group will make it clear.? I must confess that this rabbit hole is a lot deeper and wider than I had imagined but it's great to have such willing and knowledgeable guides on the journey.? BTW, I have tried a couple of on-line png to svg converters but the output give me multiple syntax errors when I past the resulting <path> contents into the appropriate function node.? Best regards, Ken, K2KXK.
Excellent.? Glad you persisted with solving the issues and now have a better idea of what is going on!? ?
?
Yes, the boundary condition of not knowing all of the button contexts at startup is bothersome, but not unsolvable!?
?
You can do one of two things.? ?
?
First, you can just create a node that sets up a copy of the streamdeckContexts after it is fully populated with buttons and then assign it to the actual Global variable.?
Then fire a message from an Inject node into it, configured to fire one time 0.5 secs after node-red starts up. This would work, it's relatively easy but not very savory as it will be a maintenance
problem when you add more SD buttons.? ? Also, it's a future out-of-sight bug in the making!
?
OR, second, take the route I use and configure node-red to allow variables to be persisted on the Operating System.? You have to modify the node-red settings.js from stock to allow this.
?
What follows is a tech note on Context Storage variables.
?
I'm running Node-Red on a raspberry Pi so,? I'll use the nano text editor.? ?Since I have my node-red settings file "protected" by changing it's owner to root (chown), I have to use sudo ahead of nano to elevate for read/write.? If you run Node-Red on a different OS, just find where the settings.js is and edit it.
?
?
Your settings.js file should be open in nano. Now use the "Where" command to do a text search--press Ctrl+w?
and type:? context storage
then press Enter
?
?
Nano will scroll down to the Context Storage section.
?
The Context Storage section is commented out by default in Node-Red.? Remove the comment characters and make your section look like this:
?
?
This will setup the ability to save / read variables that are saved to the operating system instead of running memory.
I've changed the flushInterval to 360 from the default of 30.? This mean it will only do a hard write to the SD card every 6 minutes
but if needed.
?
Now, save the file (Ctrl+w)?
?
Node-Red will need to be restarted for this change to take affect.? These two commands will do that without rebooting the Pi.
?
sudo node-red-stop
sudo node-red-start
?
You will see the startup log scroll by, and if you didn't make any typos, node-red should be running again.
Press Ctrl+c to exit from the trace log and get back to the bash prompt.
?
Now it gets interesting.? In node-red, create a function node and read the current value of the?
global SD context variable.
?
Now, turn around use the .set command to save it back ...But first...
?
You might not have noticed yet, but the .get and .set methods have optional parameters.
Now that you have enabled a second variable store called "persist"? in the settings file
?
(remember this?)
?
?
Change the .set command to use the 'persist' store instead of the default one called 'default'
?
?
It should now look like this:
?
?
Add an inject node so you can tickle this function.? Click the inject handle.
Now, refresh your Global Context variables and look what just showed up!??
Notice the different storage context ('store') show up to tell you where it is.
?
?
Now, if you restart node-red (or reboot), if you go immediately back into the Context variables you will see the 'persist' version is still there!
Now, in your flow startup area, you can switch around the functions above to read from 'persist' and save back to 'default' . Poof, you have your?
stream deck button contexts back, and you haven't pressed the Stream Deck device buttons at all!
?
Now, if you prefer, you can use the new 'persist' storage context in the "Change" node.
?
Just click the dropdown and select the desired context.? Here is the above function coded in a Change node.
The context is hard to see, but it's there...
?
So, if you wire in above change node after the sd-input node (I'd put it after I filtered off? for just the keyDown event)
then the 'persist' version of streamdeckContexts will always be up-to-date.
?
Then, finally, make another Change node that is the reverse of the above assign 'persist' to 'default'? and wire it in to fire using an auto triggering inject node at flow startup.
When you flow first starts, the streamdeckContext (in the memory or 'default' store) will get automatically put back.
?
Clear as mud right?
?
Enjoy
?
Warren, KD4Z
?
Question: Does RPi OS upgrade break node-red flows?
Hey Guys. I'm overwhelmed by the generosity of the group members in trying to educate me.? I'm taking it all in and now have a working flow with the buttons changing color as Warren showed.? I have not yet attempted sending graphics but that will be tomorrow's project.? Warren, I did use your "format for SD" node instead of the SD-Out node but still ran into trouble when I had a graphic set in the SD editor.? Once I reset that to Default, all was good.? I probably had something else miscoded.? Thanks for your explanation on the "context" property.? I had noticed the context IDs in the Global NR section and based on your comments and some testing, assumed they were populated by the? SD-In node the first time each button is pressed.? I see that Alan chose to populate the flow context with the same values instead of using the global values in his sample flow..? I assume this is because he didn't use the SD-In node but rather converted to JSON on his own.? As Alan mentioned, it would be nice if we could get NR to populate these values at start up so they don't require a push of each button.? I really enjoy learning new things and it seems like I'll be busy with the process for a while.? Thanks again for everyone's help.
Glad you have made progress!? ?Alan has extended my "Create Basic Button" idea to have more of the fun graphic stuff, which is what I was implying could be done.
I'll let Alan keep guiding you deeper with extending the options for SVG on-the-fly.? My intent was to get you to write dynamic code and not rely on hard wired PNG files.
?
Yes, the "context" is just a Globally Unique Identifier (GUID) generated when you create a button in the Stream Deck software.? It's just a 32 byte long string of characters. When you press that button, the data that comes into the websocket in node has that GUID passed as a unique way to identify that particular button.? When your code sends data back to the Stream Deck, that context is used by the Stream Deck software to figure out which button to update.? Since you got to pick the "id" (Button ID), that isn't guaranteed to be
unique. The context is used to figure out which button to change.? After all, you could have more than one button with the same "ID"
?
If you select "Context Data" in the node-red workspace screen, then scroll down and open up "Global", (click on the "refresh" icon next it too)
You should see a variable called streamdeckContexts?It is an array object, so the first time you press a Stream Deck button, you should see an element appear in this variable.
?
In my example flow, there are four buttons with id's "ant1", "ant2", "ant3" and "ant4"? So, after I have pressed each button at least one time, the streamdeckContexts variable
You can see each button has a 32 byte identifier collected in this array.? When you get to the last part of your code that generates the data to send back to the Stream Deck device,??the sd-output node does a lookup in this context array of the "button ID" that you want to update, and then grabs the button context string to pass along to the Stream Deck.
?
My sample flow included a Function node called "Format for SD" which isn't magical as it was just the original Stream Deck out node code, stripped down.? However, it appears you didn't use it originally and ran into the quirk I've found with the Stream Deck Out (sd-output) node --and that is, the design time parameters take precedence over runtime variables being passed in.? That bit caught you out (as it has me)?
?
So I present two? Stream Deck node Quirks:
?
Rule 1:? If you use the sd-input node (which is just fine) you must always configure the preceding WebSocket In node to Send/Receive "payload"? If you set it to "Entire message",
a couple bad things happen in the following sd-input node as it is poorly written and stupidly attempts to do a JSON conversion on an input that is already a JSON object.? The result is, you will see an error in the Debug window stating "SyntaxError: Unexpected token o in JSON at position 1"?
?
If you see your sd-output node show "no context", this issue is likely the cause as the code bails out with the above error before it stuffs your button's GUID into the Global streamdeckContexts variable.? ?Another reason you might see the sd-output node show "no context" is if you don't have your Stream Deck plugged into the USB port!
?
I have written my own "sd-input" function that handles this situation with a single extra line that bypasses the JSON.parse(msg.payload); statement if the payload needs that conversion.? i.e.
if (typeof msg.payload == "string")
? ? msg.payload = JSON.parse(msg.payload);
?
I've run into this issue when importing sample flows from this group!? My custom sd-input ignores this issue and also keeps track of the device identifier from the Stream Deck device as part of caching?the button context.? This allows using more that one Stream Deck with the same named button actions and they can all get broadcasted updates from each other.
?
So, just configure your websocket in to output "payload" and life will get better for you.? (double click the node, then click on the "edit pencil" button on Path, to see the configured value.
?
Rule 2:? Don't set ANYTHING at design time on Properties sheet for the sd-output node!? ?The code in the sd-output node will assume you want the design-time values and ignore runtime values passed into it. ??If you do, remove the node, and add it back into the flow without touching any properties.? ?You could also delete the Configuration Node data for that node and start it over as well.?
?
That's the two biggest rules you need to pay attention to.? There could be more.
?
I've modified my sample flow to be a complete working sample.? All you need to do is create four buttons in your Stream Deck with the ids of ant1, ant2, ant3 and ant4, Point each button to the ip address and port of your node red instance with the WebSocket endpoint of /4way? For example "ws://192.168.1.100:1880/4way
?
Also for each button, click the little down arrow at the end of the Title line (after the "T") and uncheck the "Show Title" option.? You don't want the button to have your title superimposed on top of your dynamically generated button graphic.
?
I've attached the fully working flow of the 4-Gang dynamic two line button example to this message.
event is the action you want to command to the button, in this case, "set image". ? See the StreamDeck developer document for all the available actions.
?
context is the button identification, not to be confused with the "id" you assigned the button in the config panel. ?This number is sent when you first push the button, so that future commands from Node-Red can use this id to oommand the button. ? ?Because your button graphics are not updating, I suspect you are not using the correct context number.
?
In this case, the payload is a SVG image to build a red background and some test of various size, position, and color.
?
?
Attache is my version of the SD Flow. ?It uses the same concepts that Warren showed you, but different coding.
?
The function, ""Process Stream Deck Input" will, for each unique button id (the name you gave the button) but into Node-Red flow context the context (button) and the device numbers. ?Below is the example for the button we pushed, above. ? The "device' number can be included in the command object, if you have multiple Stream Deck devices.
?
?
{"context":"b92505aa7b38be8abe13cb04ee0c242e",
"device":"3B4A178B0FA8D7408582138E1F192969",
"id":"toggle","
server":"ws://192.168.70.38:1880/streamdeck"}
?
?
Ok, Now we have everything in flow context to use the button id to search for the correspoiding context (button) and device numbers.
?
Lets look at this flow that build a gauge. ? In this gauge, we have multiple SVC components, that can be modified to your situation:
?
?
The "Build Streamdeck Button", has pre build SVG elements, background, gauge, text one, text two, switch icon, mic icon, speaker icon, and image.
?
?
At the bottom of this function, you build the button with the SVG elements you desire, in the case of the above gauge button, the line is:
"data:image/svg+xml;charset=utf8,<svg " + view_box + defs + background ?>>> is boiler plant that Stream deck needs to build the SVG image.
?
"</svg>" is the end of the SVG line.
?
The desired SVG elements are added between, derived from the element variable names above. In this case, we are using text_one, text_two, gauge, and speaker_icon.
?
Now, how to add the variables to change the SVG file to make the button dynamic. See the "Button Config" function. You can hardcode any of the gauge button parameters or you can input a dynamic value from other pass of your floe
?
In this example, the msg.gauge_pixels, is derived from the msg.payload input.....note, full scale on the gauge is 72 pixels.
?
You can also control the "tick" mark on the gauge.
?
Here is the full configuration for the gauge:
// gauge full scale = 72 pixels
msg.gauge_pixels = msg.payload
msg.tick_pixels = msg.tick
msg.icon_color = "white"
msg.icon_opacity = "0.35"
msg.tick_color = "red"
msg.background_opacity = "0.5"
msg.background_color = "black"
msg.gauge_text_low = "-90"
msg.gauge_text_hi = "-10"
msg.gauge_color_low = "white"
msg.gauge_color_hi = "red"
msg.gauge_x = "10"
msg.one_text = msg.payload
msg.two_text = "Mic Level"
msg.text_one_color = "white"
msg.text_two_color = "red"
msg.font_one_size = "20px"
msg.font_two_size = "15px"
msg.text_one_anchor = "middle"
msg.text_two_anchor = "middle"
//Note: possible anchors are: start, middle, end
msg.one_x = "36"
msg.two_x = "36"
msg.one_y = "56"
msg.two_y = "68"
msg.id = "meter"
return msg;
?
OK, now we must build the object to command Stream Deck to build the button with the SVG image.
?
It is the same object we did for the simple red background image above, but it now contains the SVG elements to build the gauge button:
Hi All.? Warren, I got your flow to work.? The problem I was having is that I assigned a graphic to the SD buttons at design time.? I guess this does not get overridden by the output of the NR flow.? So the buttons are now what your flow output:? A solid color with the appropriate text.? Is there a way to include an image as well, say a png?? Also, I'm really confused about the "context" carried by the message.? I see that in your flow, it is pointing to the Global context variables but what information is it carrying and how is it used?? Is it just an indication of how to address a specific button?? Thanks again for you help as well as Alan's and Dave's.
Alan and I were discussing this on the phone earlier. If the equipment you are controlling (example - Antenna Genius) sends status updates or can be queried for status, then that should determine what to send to the button. ?A multistate button may not be ideal but rather send static images to the buttons based on the device¡¯s status.?
The DLI Web Switch flow does just that but if you restart Node Red, you must push all eight buttons to get the button ID into context data so Node Red knows how to send websocket payload to correct button. I¡¯m going to look at how to set this context data without need to press the button.?
On Mar 8, 2025, at 3:45?PM, Ken Kayser via groups.io <kxkayser@...> wrote:
?
Hi Warren.? Thanks so much for taking the time to respond to my query and creating the example flow.? I have attempted to get it working in my environment but have not been successful.? I can follow most of the flow until you get into the svg nodes when I get somewhat lost.? Below is the output of the last node in the flow before the WebSocket out node.
?
<inline.0.part>
This is after pressing the ant1 button.? Expanding the first object, I get:
<inline.1.part>
?
However, it doesn't change the buttons on the Stream Deck.? Does this output give you an indication of what might be wrong?? What more can I supply for debugging?? Thanks again for your help.
Hi Warren.? Thanks so much for taking the time to respond to my query and creating the example flow.? I have attempted to get it working in my environment but have not been successful.? I can follow most of the flow until you get into the svg nodes when I get somewhat lost.? Below is the output of the last node in the flow before the WebSocket out node.
?
This is after pressing the ant1 button.? Expanding the first object, I get:
?
However, it doesn't change the buttons on the Stream Deck.? Does this output give you an indication of what might be wrong?? What more can I supply for debugging?? Thanks again for your help.
How about a combination of Alan's options 2 and 3 above?
2- send images for the desired button via node-red.? This is the method Dave, WO2X demonstrated
3- send SVG formatted?commands - ?Most advanced and my preferred method.
?
Here's how I do it using Dave's concept of building an SVG graphics for a button having two lines of text
and configurable background color.? No physical SVG graphics files are needed. That's the real benefit here
as creating and modifying individual graphic files can get tedious for an antenna setup with 12 selections
and two states each.? It is easily extendable and allows quick alteration of the text and colors down the road.
?
Here is a partial flow with the meat of the logic.? It assumes you have 4 antenna buttons that need to be
ganged so when one is pressed, the all four buttons change background color to indicate active or inactive state.
?
The idea is when a button is pressed, create a function that sends out four messages to the StreamDeck, altering
the button background colors.? The button SVG (text) is instantiated in a basic form, then modified
to show the appropriate background color based on it being active or inactive.
?
When a button is pressed, you capture the buttonId (and likely filter for "keyDown" only)
?
This is the logic that sends out four messages that define the four button cap states
based on which button was just pressed. One message in, four messages out.
?
?
Here is what the "4-Button ganging logic here" function spit out if "ant1" is passed in.?
?
?
The Create Basic Button function defines the button?in a generic way
(thanks to Dave, W2OX for this concept)
A new object is created with all of the desired properties for the button.
and the input payload and topic are just tacked back on.
?
?
The next function uses the buttonId in a Case statement to override the basic properties?
to suit the button being passed in and the states we want to show a particular button as.
?
Remember, this function gets called FOUR times (one for each case) when you press a single button.
?
Here is the first of four cases in that function.? They are almost all the same except for background color.
You can alter the font size and location of the two lines of text here.
?
?
The next function (again, stolen from Dave) just builds a giant string that represents an SVG graphic.
I use another function to strip out the SVG properties, as we don't need them anymore and don't need
to pass them along.?
?
I use my own stripped down version of the SD "out" node.? You can use the SD out if you choose to.
?
The result is passed back to the StreamDeck via the WebSocket Out node.
?
?
The attached flow is not a complete working example.? You will need to wire it into your existing WebSocket nodes to communicate with the StreamDeck.
Use it as an outline to create simple button caps with two lines of text.? You could of course, extend the SVG text to have more complicated graphic elements.
I lifted this from a working solution for W4AX to control four relays on a Pi Hat.? Forgive me if I left out something important while summarizing into an example.