This solution pre-dates the web based solution by a few years. I wanted a quick and easy way for my show visitors to trigger my light show so that it only ran the flashy lights when someone was actually there to watch, and reduce disturbing my neighbors.
At the time, there were a few FPP plugins available that might have done the job, but since I was already using home automation tools to do more than just control my light show, and I wanted more control to do some things I’ll describe below, I did it myself.
This guide walks through the features, key concepts and some detailed setup steps.
The objective is allow visitors to interact with the light show via SMS/text message. We want to publish a phone number to which they can text any number of commands to trigger various light show functions, including playing the entire show, playing a single sequence, retrieving light show information, donation information, or anything else you can think of. The feature should also respond to visitors by text to acknowledge receipt, provide status or other requested information, or let them know if there was an error.
I won’t get into all the details here. But once you sign up and have your DID number, assuming you don’t want to receive phone calls here, is to navigate to DID Numbers | Manage DIDs. Below, I’ve detailed the settings you should choose, and skipped those I think are irrelevant.
https://[YOUR_IP_ADDRESS_OR_DOMAIN]/[YOUR_WEBHOOK_OR_ENDPOINT]?from={FROM}&message={MESSAGE}Node-RED handles parsing the inbound text message payload and figuring out what to do with it. As a first step, you just need to get that message data into Node-RED.
msg.payload.
msg.payload.message.
$lowercase(payload.message) Using lowercase() for comparison.| Output | Rule Type | Command Match | Destination |
|---|---|---|---|
| Output 1 | Equals | info |
Respond with instructions & link to website. |
| Output 2 | Equals | donate |
Respond with info & link to my favorite charity. |
| Output 3 | RegEx | ^go(\d+)?$ |
The main play/error path. Matches anything starting with go. |
| Output 4 | Equals | bday |
Plays a special birthday sequence for a friend & overrides ‘checks’. |
| Output 5 | Otherwise | (Default) | Respond with, “I didn’t understand, reply with info for help.” |
If the incoming command matches the “go” regex (ie, is go alone or followed by a number) and is routed out the main play/error path, the system performs a series of prerequisite checks before fulfilling the request. These will vary based on what is important to you. Here are some samplee cases to test for:
fpp01/falcon/player/FPP/status to confirm the player is idle. If it fails, the system replies saying, “Sorry. Something else is playing now. Try again when it finishes.”If the received command passes all the checks, it’s time to play something. My show plays in three modes:
Randomized Playlist: When my show ‘starts up’ at sunset every night, it checks the date and then populates a HomeAssistant input_select.fpp_sequences entity from the holiday-specific playlists set up in FPP. If the command is go (or go0, but no one does this), it checks an input_select.song_playlist entity for length (this will make sense in a minute).
If the length is <= 1, Node-RED randomizes the items from input_select.fpp_sequences, populates the input_select.song_playlist entity with the full randomized list, then plays from that list. As my Halloween and Christmas shows have 30+ sequences each and few people will sit for hours to watch all of them in one session, I play a set of 4-6 sequences at a time. When it’s done, if they want more, the visitor can text go again to play the next set, picking up where they left off. Since the playlist has more than one entry, it will not re-randomize on subsequent triggers.
Specific, Selected Sequence: If the command is goN (where N is a non-zero number), Node-RED performs a lookup against input_select.fpp_sequences, gets the title of the Nth sequence, puts it in input_select.song_playlist and plays it.
Single, Randomized Sequence (on a timer): Not directly related to the on-demand feature, I also have a timer running to play a random sequence every 15 minutes. When this executes, it runs the same randomization flow as the Randomized Playlist above, but populates input_select.song_playlist, with only the first song. The idea here is that if a visitor triggers 1 or 2 sets then leaves, this timed event will fire about 15 minutes after the last sequence was played.
In the two latter scenarios, since input_select.song_playlist has only one entry, the next visitor to trigger the Randomized Playlist flow with go will get a new, randomized playlist.
Playing a sequence from Node-RED is pretty straightfoward.
msg.payload.{"command":"Start Playlist","args":["{{payload}}.fseq",false,false]}).fpp01/falcon/player/FPP/set/command topic.I have about 10 total possible SMS replies to all of the above various situations. There are numerous ways one could go about managing them, including hard-coding into Change nodes or consolidating into a single Function node (which I’m considering). For now, though, I use a HomeAssistant input_text helper entity for each response message that I call with a HomeAssistant Current State node.
Whether it’s a reply in response to an information request, a failure on one of the prerequisite checks, or letting the visitor know “The show is starting”, I pull in the appropriate message and save it to msg.data. I use a HomeAssistant Action node to call rest_command.sms_reply service because it’s already set up for other uses. But as you will see, you could simply send the message with an HTTP Request node.
msg.payload.input_text.off_season).msg.data = entity state.msg.datadata & " Visit https://lightsongranger.com for more info." (JSONata)rest_command service to send the message via VoIP.ms.
rest_command.sms_reply (or whatever you’ve named your service, see below).{"dst":"{{payload.from}}","message":"{{{data}}}"}To send the SMS message, use the VoIP.ms API to send a GET request like this:
https://voip.ms/api/v1/rest.php?api_username=[YOUR_VOIPMS_USERNAME]&api_password=[YOUR_VOIPMS_PASSWORD]&method=sendSMS&did=[YOUR_VOIPMS_PHONE_NUMBER]&dst={{ dst }}&message={{ message }}"If using HomeAssistant, add this to your configuration.yaml under your rest_command section:
sms_reply:
url: "https://voip.ms/api/v1/rest.php?api_username=[YOUR_VOIPMS_USERNAME]&api_password=[YOUR_VOIPMS_PASSWORD]&method=sendSMS&did=[YOUR_VOIPMS_PHONE_NUMBER]&dst={{ dst }}&message={{ message }}"
method: getEven though I recently added the ability to trigger the show from a web page, thus far I still have many more visitors using this SMS/text method. Few seem that interested in selecting specific songs and instead prefer triggering a set from the playlist, then sitting back to watch whatever plays.
But whichever method, I do think having an on-demand option to limit the playing of flashy sequences when no one is watching goes a long way to appease any neighbors who might be slightly (or more) annoyed with the show and traffic.
I hope this has been helpful and inspires you to make your own.