Node-Red Palette: Common Choices

Thanks for the quick feedback. I will probably try that one. It looks more powerful (though more complex as lots of thinking in terms of JSON). That said, I build a lot of function nodes so complexity in pursuit of a desired outcome isn't the worst thing.

1 Like

It's just that in my years of coding I never used the FSM concept so it is not something I am completely comfortable with yet. I think it is a cool idea and can be used to solve specific problems but imagine there is a complexity limit were it becomes impractical.

I do like writing function nodes too - easy compact way of getting things done the way you want. Keep in mind that the function node runs in a sandbox so can potentially slow things down if calling it iteratively etc. not sure about the impact of the sandbox so striking it out.

At home I almost always only have 2-3 states max, so no real reason to use a FSM.

FSM can be really handy when you have a LOT of states and transition scenarios, though. Or if you want to do something different specifically on the specific transition happening, and not just the new state. I use it at work a lot on complex controls. That said, I always found FSM more work than benefit with only 2-3 states.

1 Like

Well for my simple learning use-case - a 4 state transition (home/away/guest-home/guest-away) it's working pretty well. Much beyond that and I guess I would have to start mainlining ibuprofen for the epic headaches that would occur... :laughing: :dizzy_face:

I have seen a lot of references to the potential slowdown from function nodes (including ways to get around the sandboxing at the cost of security risk), but have never been able to experience a downside. There is one downside, it makes it hard to share with anyone that has less javascript experience than you have and for complex functions any programmer regardless of experience can have a hard time slogging through someone else's code.

The new nice answer is encapsulate your function nodes in a subflow then convert your subflow to a custom module!!!! Works great!!!!

1 Like

That would work great as long as you don't put any flow specific info into the function code itself (a quick and slightly hacky workaround).

Yep - but you can control a lot of that through environment variables and msg properties.

I am starting to play around with custom modules because I can create a set of nodes for my clients that are not as easily messed with and I can update via remote access . It's very promising so far.

The example situation I am trying to learn is this:
I have an old iPhone that sits in place as a podcast player. I found however that the battery eventually went dead and took the phone down with it from constantly being 100% charged. So no I have started to charge it, then turn off the outlet let it run down and then restart charging by powering the outlet back up.

I have found that when the power comes up, because it is connected a speaker via bluetooth, it starts playing, so I have to disconnect it temporarily from bluetooth before turning on the power. This is the diagram of the FSM:
image

If this works out well (and I think it is very close other than the weird redeploy behavior with the persistent-fsm node), then I plan to go after climate control where I factor in all of these things:

  1. Upstairs vs Downstairs Thermostat/System
  2. Heating/Cooling/Off
  3. Fan On/Circulate/Auto
  4. Future weather forecast (willing to let it get a little uncomfortable if nature will heat or cool my house tomorrow)
  5. Room by room temperature (potentially driving Fan condition)

I hope to eventually have automated dampers for airflow, but the list above is enough complexity to get started.

How do you detect the power situation? through the smart plug? Also how does the system know the device's bluetooth has been connected or not?

Here's my take on that FSM - but again I am still new to this concept so ymmv.

Sample FSM - requires the node-red-contrib-finite-state-machine

[{"id":"7c7d6927.99e3b8","type":"finite-state-machine","z":"af91369d.586338","name":"","fsmDefinition":"{\"state\":{\"status\":\"iPhoneCharged_BTConnected\"},\"transitions\":{\"iPhoneCharged_BTConnected\":{\"low_charge\":\"iPhoneNotCharged_BTConnected\",\"bt_disconnected\":\"iPhoneCharged_BTDisconnected\"},\"iPhoneCharged_BTDisconnected\":{\"low_charge\":\"iPhoneNotCharged_BTDisconnected\",\"bt_connected\":\"iPhoneCharged_BTConnected\"},\"iPhoneNotCharged_BTConnected\":{\"full_charge\":\"iPhoneCharged_BTConnected\",\"bt_disconnected\":\"iPhoneCharged_BTDisconnected\"},\"iPhoneNotCharged_BTDisconnected\":{\"full_charge\":\"iPhoneCharged_BTDisconnected\",\"bt_connected\":\"iPhoneNotCharged_BTConnected\"}}}","sendInitialState":true,"sendStateWithoutChange":false,"showTransitionErrors":false,"x":730,"y":2880,"wires":[["a107ad4c.acd0d"]]},{"id":"9847816c.c5905","type":"inject","z":"af91369d.586338","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"low_charge","x":410,"y":2800,"wires":[["7c7d6927.99e3b8"]]},{"id":"e5092892.105dc8","type":"inject","z":"af91369d.586338","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"full_charge","x":410,"y":2840,"wires":[["7c7d6927.99e3b8"]]},{"id":"13de600d.e37ca","type":"inject","z":"af91369d.586338","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"bt_connected","x":410,"y":2920,"wires":[["7c7d6927.99e3b8"]]},{"id":"7ee08740.a97f48","type":"inject","z":"af91369d.586338","name":"","props":[{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"bt_disconnected","x":420,"y":2960,"wires":[["7c7d6927.99e3b8"]]},{"id":"a107ad4c.acd0d","type":"switch","z":"af91369d.586338","name":"iPhoneCharged_BTConnected \\n iPhoneCharged_BTDisconnected \\n iPhoneNotCharged_BTConnected \\n iPhoneNotCharged_BTDisconnected","property":"payload.status","propertyType":"msg","rules":[{"t":"eq","v":"iPhoneCharged_BTConnected","vt":"str"},{"t":"eq","v":"iPhoneCharged_BTDisconnected","vt":"str"},{"t":"eq","v":"iPhoneNotCharged_BTConnected","vt":"str"},{"t":"eq","v":"iPhoneNotCharged_BTDisconnected","vt":"str"}],"checkall":"true","repair":false,"outputs":4,"x":1090,"y":2880,"wires":[["9811a637.f37668"],["826246ab.d01458"],["6b6a2b37.708874"],["8a72cf27.6f95e"]]},{"id":"9811a637.f37668","type":"debug","z":"af91369d.586338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.status","targetType":"msg","statusVal":"","statusType":"auto","x":1510,"y":2820,"wires":[]},{"id":"826246ab.d01458","type":"debug","z":"af91369d.586338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.status","targetType":"msg","statusVal":"","statusType":"auto","x":1510,"y":2860,"wires":[]},{"id":"6b6a2b37.708874","type":"debug","z":"af91369d.586338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.status","targetType":"msg","statusVal":"","statusType":"auto","x":1510,"y":2900,"wires":[]},{"id":"8a72cf27.6f95e","type":"debug","z":"af91369d.586338","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload.status","targetType":"msg","statusVal":"","statusType":"auto","x":1510,"y":2940,"wires":[]}]

Unfortunately, the power situation is a pain involving extra complexity. I am using the Apple iCloud integration within Home Assistant to get the battery readings of the iPhone every 30 minutes. I have looked at Home Assistant enough to see that it could become a bottomless pit of time consumption, but I am really only using it for iCloud and to act as a Homekit Controller. I feed all of that info to Node Red.

The bluetooth speaker happens to be an Amazon Echo and so using the cakebaked Alexa nodes, I can get the bluetooth connection status into Node Red.
Edit: I also use the Alexa nodes to disconnect and reconnect the iPhone to Echo bluetooth connection.

My new FSM looks quit similar to what you have. Here is the JSON I created:

{
    "state": {
        "status": "Needs Power Bluetooth Disconnected"
    },
    "transitions": {
        "Needs Power Bluetooth Connected": {
            "Disconnected Bluetooth": "Needs Power Bluetooth Disconnected"
        },
        "Needs Power Bluetooth Disconnected": {
            "Charging Started": "Charging Bluetooth Disconnected"
        },
        "Charging Bluetooth Disconnected": {
            "Reconnected Bluetooth": "Charging Bluetooth Connected"
        },
        "Charging Bluetooth Connected": {
            "Charged to Desired Level": "Finished Charging"
        },
        "Finished Charging": {
            "Low Power Detected": "Needs Power Bluetooth Connected"
        }
    }
}

The one thing I am trying to figure out is the persistent FSM had the option of something like this to say from any state when this tranistion happens go to that state. Kind of the equivalent of this JSON inside transitions:

"*": {
    "Low Power Detected": "Needs Power Bluetooth Connected"
}

This doesn't actually seem to work here and so I am wondering if it is just syntax or if I just need to build all of the combinations into my JSON.

Edit 2: Turns out it was not that hard to essentially turn Low Power detected into a reset via a little cut and paste in the JSON:

{
    "state": {
        "status": "Needs Power Bluetooth Disconnected"
    },
    "transitions": {
        "Needs Power Bluetooth Connected": {
            "Disconnected Bluetooth": "Needs Power Bluetooth Disconnected",
            "Low Power Detected": "Needs Power Bluetooth Connected"
        },
        "Needs Power Bluetooth Disconnected": {
            "Charging Started": "Charging Bluetooth Disconnected",
            "Low Power Detected": "Needs Power Bluetooth Connected"
        },
        "Charging Bluetooth Disconnected": {
            "Reconnected Bluetooth": "Charging Bluetooth Connected",
            "Low Power Detected": "Needs Power Bluetooth Connected"
        },
        "Charging Bluetooth Connected": {
            "Charged to Desired Level": "Finished Charging",
            "Low Power Detected": "Needs Power Bluetooth Connected"
        },
        "Finished Charging": {
            "Low Power Detected": "Needs Power Bluetooth Connected"
        }
    }
}
1 Like

Okay cool - I find this stuff interesting and your take on it gives me some things to think about. My original idea was that things like "charged" and "connected" actions are transitions while device states like "BTConnected Low Power" are, well, "states".

States:
BT Connected / Low Power
BT Disconnected / Low Power
BT Connected / Charged to Desired State
BT Disconnected / Charged to Desired State

and transitions:
charging
connecting
charged
connected

Note: Added connecting and charging which just transition back to the same state until done...

{
    "state": {
        "status": "iPhoneCharged_BTConnected"
    },
    "transitions": {
        "iPhoneCharged_BTConnected": {
            "low_charge": "iPhoneNotCharged_BTConnected",
            "bt_disconnected": "iPhoneCharged_BTDisconnected"
        },
        "iPhoneCharged_BTDisconnected": {
            "low_charge": "iPhoneNotCharged_BTDisconnected",
            "bt_connected": "iPhoneCharged_BTConnected"
        },
        "iPhoneNotCharged_BTConnected": {
            "full_charge": "iPhoneCharged_BTConnected",
            "bt_disconnected": "iPhoneCharged_BTDisconnected",
			"charging": "iPhoneNotCharged_BTConnected"
        },
        "iPhoneNotCharged_BTDisconnected": {
            "full_charge": "iPhoneCharged_BTDisconnected",
            "bt_connected": "iPhoneNotCharged_BTConnected",
            "connecting": "iPhoneNotCharged_BTDisconnected"
        }
    }
}

I use the node-red-contrib-join-wait node.

It works to trigger when two events are true within a set time frame.

1 Like

You could also use the system "trigger" node.. or maybe "simple-message-queue" as well depending upon the use-case.

Saw that node but I see that it doesn't evaluate the order in which the messages arrive, which is what I needed for my particular case.

you can use it to specify a specific sequence order. there is a drop down box to select that setting, then you specify how the paths are listed.

if you wanted to have different actions based on different sequences, you’d have to have separate nodes for each sequence.

1 Like

Good to know - thanks!

Coding question. How would I put two of these camera displays on the same dashboard? I want them different sizes, one is just to check the garage is shut, and dont need it to be 625px. I had them both working on the same page as different elementId's, but if I try and have two of these on the same dash, only 1 camera shows up. All paths are correct (if I disable one, the other camera works, and visa versa). This is in a node red UI Template Node.

  <!DOCTYPE html>
  <html>
  <style>
  img {
border: 1px solid #ddd;
border-radius: 8px;
padding: 2px;
width: 630px;
  }
  </style>

 <script type="text/javascript">
 scope.$watch('msg', function(msg) {
    inMessage(msg.payload);
 });

 function updatePic() {
    document.getElementById('z52').src = 'removed';
         //alert('updated pics');
 }

 function inMessage(event) {
     if (event.match('checkWeb')) {
        updatePic();
}
 }

 </script>
 <center>
 <table>
     <tr><!-- Row 1 -->
		 		    <td style="text-align: center"><img src="" id="z52" /></td>

</tr>

 </table>
 </center>
 </html>

Edit: updated crazy formating.

I finally got Sonos TTS going in Node Red via the recently added palette
node-red-contrib-tts-ultimate

Good news is on the Sonos Beam when currently playing via the television and a tts comes through it returns to the television audio after the tts automatically. Unlike using RM where I had to add a delay and an action to go to the url that the beam was playing prior to the tts playing to every rule that played a tts message.

Bad news is still unable to get it to return to playing spotify after a tts has occurred automatically and have to go back into the app and initiate playing it again after every tts message.

Hopefully someday they will find a fix for this and update.

Thanks for bringing this palette up - looks very interesting. I have not played around with TTS all that much but do have Sonos...

I noticed on the site that the maintainer said it's a Sonos API documentation issue.. which I guess isn't terrible news if it's just an undocumented feature.

  • Automatic resume of music queue (including radio stations, but here, some users reports problem resuming radio stations and, because of lack of Sonos API documentation, the issue cannot currently be fixed), at exact track, at exact time.