Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save okets/c7baea968aab019a09c9d2c80df29d40 to your computer and use it in GitHub Desktop.
Save okets/c7baea968aab019a09c9d2c80df29d40 to your computer and use it in GitHub Desktop.
iOS Subflow for HomeAssistant Companion notifications
[
{
"id":"914734122ce79fcd",
"type":"subflow",
"name":"iOS Actionable Notification",
"info":"[Documentation](https://github.com/zachowj/node-red-contrib-home-assistant-websocket/discussions/379)\n",
"category":"home_assistant",
"in":[
{
"x":60,
"y":60,
"wires":[{"id":"f8d958779acdc007"}]
}
],
"out":[
{
"x":1440,
"y":160,
"wires":[{"id":"7bb055c340123ca6","port":0}]
},
{
"x":1440,
"y":200,
"wires":[{"id":"7bb055c340123ca6","port":1}]
},
{
"x":1440,
"y":240,
"wires":[{"id":"7bb055c340123ca6","port":2}]
},
{
"x":1440,
"y":280,
"wires":[{"id":"7bb055c340123ca6","port":3}]
}
],
"env":[
{
"name":"group",
"type":"str",
"value":"None",
"ui":{"label":{"en-US":"Group Name"}}
},
{
"name":"tag",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Tag (for replacing messages - optional)"
}
}
},
{
"name":"service",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Notify Service"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"title",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Title"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"subtitle",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Subtitle (optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"message",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Message"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"notificationUrl",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Notification URL (optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"customSoundPreInstalled",
"type":"str",
"value":"default",
"ui":{
"label":{"en-US":"Pre-installed Custom Sound"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"default"},"v":"default"},
{"l":{"en-US":"No Sound"},"v":"none"},
{
"l":{
"en-US":"US-EN-Alexa-Back-Door-Opened.wav"
},
"v":"US-EN-Alexa-Back-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Back-Door-Unlocked.wav"
},
"v":"US-EN-Alexa-Back-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Basement-Door-Opened.wav"
},
"v":"US-EN-Alexa-Basement-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Basement-Door-Unlocked.wav"
},
"v":"US-EN-Alexa-Basement-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Boyfriend-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Boyfriend-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Daughter-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Daughter-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Front-Door-Opened.wav"
},
"v":"US-EN-Alexa-Front-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Front-Door-Unlocked.wav"
},
"v":"US-EN-Alexa-Front-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Garage-Door-Opened.wav"
},
"v":"US-EN-Alexa-Garage-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Girlfriend-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Girlfriend-Is-Arriving.wav"
},
{
"l":{"en-US":"US-EN-Alexa-Good-Morning.wav"},
"v":"US-EN-Alexa-Good-Morning.wav"
},
{
"l":{"en-US":"US-EN-Alexa-Good-Night.wav"},
"v":"US-EN-Alexa-Good-Night.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Husband-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Husband-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Mail-Has-Arrived.wav"
},
"v":"US-EN-Alexa-Mail-Has-Arrived.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-At-Back-Door.wav"
},
"v":"US-EN-Alexa-Motion-At-Back-Door.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-At-Front-Door.wav"
},
"v":"US-EN-Alexa-Motion-At-Front-Door.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-Detected-Generic.wav"
},
"v":"US-EN-Alexa-Motion-Detected-Generic.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-In-Back-Yard.wav"
},
"v":"US-EN-Alexa-Motion-In-Back-Yard.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-In-Basement.wav"
},
"v":"US-EN-Alexa-Motion-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-In-Front-Yard.wav"
},
"v":"US-EN-Alexa-Motion-In-Front-Yard.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Motion-In-Garage.wav"
},
"v":"US-EN-Alexa-Motion-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Patio-Door-Opened.wav"
},
"v":"US-EN-Alexa-Patio-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Patio-Door-Unlocked.wav"
},
"v":"US-EN-Alexa-Patio-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Smoke-Detected-Generic.wav"
},
"v":"US-EN-Alexa-Smoke-Detected-Generic.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Smoke-Detected-In-Basement.wav"
},
"v":"US-EN-Alexa-Smoke-Detected-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Smoke-Detected-In-Garage.wav"
},
"v":"US-EN-Alexa-Smoke-Detected-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Smoke-Detected-In-Kitchen.wav"
},
"v":"US-EN-Alexa-Smoke-Detected-In-Kitchen.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Son-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Son-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Water-Detected-Generic.wav"
},
"v":"US-EN-Alexa-Water-Detected-Generic.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Water-Detected-In-Basement.wav"
},
"v":"US-EN-Alexa-Water-Detected-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Water-Detected-In-Garage.wav"
},
"v":"US-EN-Alexa-Water-Detected-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Water-Detected-In-Kitchen.wav"
},
"v":"US-EN-Alexa-Water-Detected-In-Kitchen.wav"
},
{
"l":{"en-US":"US-EN-Alexa-Welcome-Home.wav"},
"v":"US-EN-Alexa-Welcome-Home.wav"
},
{
"l":{
"en-US":"US-EN-Alexa-Wife-Is-Arriving.wav"
},
"v":"US-EN-Alexa-Wife-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Back-Door-Motion.wav"
},
"v":"US-EN-Daisy-Back-Door-Motion.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Back-Door-Open.wav"
},
"v":"US-EN-Daisy-Back-Door-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Front-Door-Motion.wav"
},
"v":"US-EN-Daisy-Front-Door-Motion.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Front-Door-Open.wav"
},
"v":"US-EN-Daisy-Front-Door-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Front-Window-Open.wav"
},
"v":"US-EN-Daisy-Front-Window-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Garage-Door-Open.wav"
},
"v":"US-EN-Daisy-Garage-Door-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Guest-Bath-Leak.wav"
},
"v":"US-EN-Daisy-Guest-Bath-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Kitchen-Sink-Leak.wav"
},
"v":"US-EN-Daisy-Kitchen-Sink-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Kitchen-Window-Open.wav"
},
"v":"US-EN-Daisy-Kitchen-Window-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Laundry-Room-Leak.wav"
},
"v":"US-EN-Daisy-Laundry-Room-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Master-Bath-Leak.wav"
},
"v":"US-EN-Daisy-Master-Bath-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Master-Bedroom-Window-Open.wav"
},
"v":"US-EN-Daisy-Master-Bedroom-Window-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Office-Window-Open.wav"
},
"v":"US-EN-Daisy-Office-Window-Open.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Refrigerator-Leak.wav"
},
"v":"US-EN-Daisy-Refrigerator-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Daisy-Water-Heater-Leak.wav"
},
"v":"US-EN-Daisy-Water-Heater-Leak.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Back-Door-Closed.wav"
},
"v":"US-EN-Morgan-Freeman-Back-Door-Closed.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Back-Door-Locked.wav"
},
"v":"US-EN-Morgan-Freeman-Back-Door-Locked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Back-Door-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Back-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Back-Door-Unlocked.wav"
},
"v":"US-EN-Morgan-Freeman-Back-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Basement-Door-Closed.wav"
},
"v":"US-EN-Morgan-Freeman-Basement-Door-Closed.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Basement-Door-Locked.wav"
},
"v":"US-EN-Morgan-Freeman-Basement-Door-Locked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Basement-Door-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Basement-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Basement-Door-Unlocked.wav"
},
"v":"US-EN-Morgan-Freeman-Basement-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Boss-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Boss-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Boyfriend-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Boyfriend-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Cleaning-Supplies-Closet-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Cleaning-Supplies-Closet-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Coworker-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Coworker-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Daughter-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Daughter-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Friend-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Friend-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Front-Door-Closed.wav"
},
"v":"US-EN-Morgan-Freeman-Front-Door-Closed.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Front-Door-Locked.wav"
},
"v":"US-EN-Morgan-Freeman-Front-Door-Locked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Front-Door-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Front-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Front-Door-Unlocked.wav"
},
"v":"US-EN-Morgan-Freeman-Front-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Garage-Door-Closed.wav"
},
"v":"US-EN-Morgan-Freeman-Garage-Door-Closed.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Garage-Door-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Garage-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Girlfriend-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Girlfriend-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Good-Morning.wav"
},
"v":"US-EN-Morgan-Freeman-Good-Morning.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Good-Night.wav"
},
"v":"US-EN-Morgan-Freeman-Good-Night.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Liquor-Cabinet-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Liquor-Cabinet-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-Detected.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-Detected.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Basement.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Bedroom.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Bedroom.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Game-Room.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Game-Room.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Garage.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Kitchen.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Kitchen.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Living-Room.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Living-Room.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Theater.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Theater.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Motion-In-Wine-Cellar.wav"
},
"v":"US-EN-Morgan-Freeman-Motion-In-Wine-Cellar.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Patio-Door-Closed.wav"
},
"v":"US-EN-Morgan-Freeman-Patio-Door-Closed.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Patio-Door-Locked.wav"
},
"v":"US-EN-Morgan-Freeman-Patio-Door-Locked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Patio-Door-Opened.wav"
},
"v":"US-EN-Morgan-Freeman-Patio-Door-Opened.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Patio-Door-Unlocked.wav"
},
"v":"US-EN-Morgan-Freeman-Patio-Door-Unlocked.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Roommate-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Searching-For-Car-Keys.wav"
},
"v":"US-EN-Morgan-Freeman-Searching-For-Car-Keys.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Setting-The-Mood.wav"
},
"v":"US-EN-Morgan-Freeman-Setting-The-Mood.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smartthings-Detected-A-Flood.wav"
},
"v":"US-EN-Morgan-Freeman-Smartthings-Detected-A-Flood.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smartthings-Detected-Carbon-Monoxide.wav"
},
"v":"US-EN-Morgan-Freeman-Smartthings-Detected-Carbon-Monoxide.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smartthings-Detected-Smoke.wav"
},
"v":"US-EN-Morgan-Freeman-Smartthings-Detected-Smoke.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smoke-Detected-In-Basement.wav"
},
"v":"US-EN-Morgan-Freeman-Smoke-Detected-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smoke-Detected-In-Garage.wav"
},
"v":"US-EN-Morgan-Freeman-Smoke-Detected-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Smoke-Detected-In-Kitchen.wav"
},
"v":"US-EN-Morgan-Freeman-Smoke-Detected-In-Kitchen.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Someone-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Someone-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Son-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Son-Is-Arriving.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Starting-Movie-Mode.wav"
},
"v":"US-EN-Morgan-Freeman-Starting-Movie-Mode.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Starting-Party-Mode.wav"
},
"v":"US-EN-Morgan-Freeman-Starting-Party-Mode.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Starting-Romance-Mode.wav"
},
"v":"US-EN-Morgan-Freeman-Starting-Romance-Mode.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-All-The-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-All-The-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Air-Conditioner.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Air-Conditioner.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Bar-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Bar-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Chandelier.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Chandelier.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Family-Room-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Family-Room-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Hallway-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Hallway-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Kitchen-Light.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Kitchen-Light.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Light.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Light.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-Mood-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-Mood-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-Off-The-TV.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-Off-The-TV.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Air-Conditioner.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Air-Conditioner.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Bar-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Bar-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Chandelier.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Chandelier.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Family-Room-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Family-Room-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Hallway-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Hallway-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Kitchen-Light.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Kitchen-Light.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Light.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Light.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-Mood-Lights.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-Mood-Lights.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Turning-On-The-TV.wav"
},
"v":"US-EN-Morgan-Freeman-Turning-On-The-TV.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Vacate-The-Premises.wav"
},
"v":"US-EN-Morgan-Freeman-Vacate-The-Premises.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Water-Detected-In-Basement.wav"
},
"v":"US-EN-Morgan-Freeman-Water-Detected-In-Basement.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Water-Detected-In-Garage.wav"
},
"v":"US-EN-Morgan-Freeman-Water-Detected-In-Garage.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Water-Detected-In-Kitchen.wav"
},
"v":"US-EN-Morgan-Freeman-Water-Detected-In-Kitchen.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Welcome-Home.wav"
},
"v":"US-EN-Morgan-Freeman-Welcome-Home.wav"
},
{
"l":{
"en-US":"US-EN-Morgan-Freeman-Wife-Is-Arriving.wav"
},
"v":"US-EN-Morgan-Freeman-Wife-Is-Arriving.wav"
}
]
}
}
},
{
"name":"customSound",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Custom Sound (Optional - will override pre-installed selection)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"interruptionLevel",
"type":"str",
"value":"active",
"ui":{
"label":{"en-US":"Interruption Level"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"Passive"},"v":"passive"},
{
"l":{"en-US":"Active (Default)"},
"v":"active"
},
{
"l":{"en-US":"Time Sensitive"},
"v":"time-sensitive"
},
{"l":{"en-US":"Critical"},"v":"critical"}
]
}
}
},
{
"name":"userInfo",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Populate User Information"},
"type":"checkbox"
}
},
{
"name":"isClearNotificationsOnAction",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Clear notifications on Action Received?"
},
"type":"checkbox"
}
},
{
"name":"action1Title",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 1 Title"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action1Uri",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 1 URL (optional)"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action1ActivationMode",
"type":"str",
"value":"background",
"ui":{
"label":{"en-US":"Action 1 Activation Mode"},
"type":"select",
"opts":{
"opts":[
{
"l":{"en-US":"Background"},
"v":"background"
},
{
"l":{"en-US":"Foreground"},
"v":"foreground"
}
]
}
}
},
{
"name":"action1AuthenticationRequired",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Action 1 App Authentication Required?"
},
"type":"checkbox"
}
},
{
"name":"action1Destructive",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Action 1 Destructive?"},
"type":"checkbox"
}
},
{
"name":"action1Behavior",
"type":"str",
"value":"default",
"ui":{
"label":{"en-US":"Action 1 Behavior"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"Default"},"v":"default"},
{
"l":{"en-US":"Text Input"},
"v":"textInput"
}
]
}
}
},
{
"name":"action1TextInputButtonTitle",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 1 Text Input Button Title (Required if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action1TextInputPlaceHolder",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 1 Text Input Placeholder (Optional - only if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action1Icon",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 1 Icon (Optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action2Title",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 2 Title"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action2Uri",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 2 URL (optional)"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action2ActivationMode",
"type":"str",
"value":"background",
"ui":{
"label":{"en-US":"Action 2 Activation Mode"},
"type":"select",
"opts":{
"opts":[
{
"l":{"en-US":"Background"},
"v":"background"
},
{
"l":{"en-US":"Foreground"},
"v":"foreground"
}
]
}
}
},
{
"name":"action2AuthenticationRequired",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Action 2 App Authentication Required?"
},
"type":"checkbox"
}
},
{
"name":"action2Destructive",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Action 2 Destructive?"},
"type":"checkbox"
}
},
{
"name":"action2Behavior",
"type":"str",
"value":"default",
"ui":{
"label":{"en-US":"Action 2 Behavior"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"Default"},"v":"default"},
{
"l":{"en-US":"Text Input"},
"v":"textInput"
}
]
}
}
},
{
"name":"action2TextInputButtonTitle",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 2 Text Input Button Title (Required if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action2TextInputPlaceHolder",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 2 Text Input Placeholder (Optional - only if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action2Icon",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 2 Icon (Optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action3Title",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 3 Title"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action3Uri",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 3 URL (optional)"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action3ActivationMode",
"type":"str",
"value":"background",
"ui":{
"label":{"en-US":"Action 3 Activation Mode"},
"type":"select",
"opts":{
"opts":[
{
"l":{"en-US":"Background"},
"v":"background"
},
{
"l":{"en-US":"Foreground"},
"v":"foreground"
}
]
}
}
},
{
"name":"action3AuthenticationRequired",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Action 3 App Authentication Required?"
},
"type":"checkbox"
}
},
{
"name":"action3Destructive",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Action 3 Destructive?"},
"type":"checkbox"
}
},
{
"name":"action3Behavior",
"type":"str",
"value":"default",
"ui":{
"label":{"en-US":"Action 3 Behavior"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"Default"},"v":"default"},
{
"l":{"en-US":"Text Input"},
"v":"textInput"
}
]
}
}
},
{
"name":"action3TextInputButtonTitle",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 3 Text Input Button Title (Required if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action3TextInputPlaceHolder",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 3 Text Input Placeholder (Optional - only if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action3Icon",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 3 Icon (Optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action4Title",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 4 Title"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action4Uri",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 4 URL (optional)"},
"type":"input",
"opts":{"types":["str"]}
}
},
{
"name":"action4ActivationMode",
"type":"str",
"value":"background",
"ui":{
"label":{"en-US":"Action 4 Activation Mode"},
"type":"select",
"opts":{
"opts":[
{
"l":{"en-US":"Background"},
"v":"background"
},
{
"l":{"en-US":"Foreground"},
"v":"foreground"
}
]
}
}
},
{
"name":"action4AuthenticationRequired",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Action 4 App Authentication Required?"
},
"type":"checkbox"
}
},
{
"name":"action4Destructive",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Action 4 Destructive?"},
"type":"checkbox"
}
},
{
"name":"action4Behavior",
"type":"str",
"value":"default",
"ui":{
"label":{"en-US":"Action 4 Behavior"},
"type":"select",
"opts":{
"opts":[
{"l":{"en-US":"Default"},"v":"default"},
{
"l":{"en-US":"Text Input"},
"v":"textInput"
}
]
}
}
},
{
"name":"action4TextInputButtonTitle",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 4 Text Input Button Title (Required if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action4TextInputPlaceHolder",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Action 4 Text Input Placeholder (Optional - only if behavior is Text Input)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"action4Icon",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Action 4 Icon (Optional)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"latitudeFirst",
"type":"num",
"value":"",
"ui":{
"label":{"en-US":"Latitude for Pin 1"},
"type":"input",
"opts":{"types":["num","env"]}
}
},
{
"name":"longitudeFirst",
"type":"num",
"value":"",
"ui":{
"label":{"en-US":"Longitude for Pin 1"},
"type":"input",
"opts":{"types":["num","env"]}
}
},
{
"name":"latitudeSecond",
"type":"num",
"value":"",
"ui":{
"label":{"en-US":"Latitude for Pin 2"},
"type":"input",
"opts":{"types":["num","env"]}
}
},
{
"name":"longitudeSecond",
"type":"num",
"value":"",
"ui":{
"label":{"en-US":"Longitude for Pin 2"},
"type":"input",
"opts":{"types":["num","env"]}
}
},
{
"name":"showLineBetweenPoints",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Show a line between points?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"showCompass",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Show a compass on the map?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"showPointsOfInterest",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Show points of interest?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"showScale",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Show scale information on the map?"
},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"showTraffic",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Show Traffic?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"showUserLocation",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Show User Location?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"cameraEntity",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Camera Entity"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"imagePath",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Image Path (10MB limit)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"videoPath",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Video Path (50MB limit)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"audioPath",
"type":"str",
"value":"",
"ui":{
"label":{"en-US":"Audio Path (5MB limit)"},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"contentUrl",
"type":"str",
"value":"",
"ui":{
"label":{
"en-US":"Content URL (overrides image/video/audio)"
},
"type":"input",
"opts":{"types":["str","env"]}
}
},
{
"name":"lazyLoading",
"type":"bool",
"value":"false",
"ui":{
"label":{
"en-US":"Load Media in Notification Lazily?"
},
"type":"input",
"opts":{"types":["bool","env"]}
}
},
{
"name":"hideThumbnail",
"type":"bool",
"value":"false",
"ui":{
"label":{"en-US":"Hide thumbnail?"},
"type":"input",
"opts":{"types":["bool","env"]}
}
}
],
"meta":{},
"color":"#D8BFD8",
"outputLabels":[
"Action 1",
"Action 2",
"Action 3",
"Cleared"
],
"icon":"font-awesome/fa-mobile-phone",
"status":{
"x":200,
"y":320,
"wires":[{"id":"f87ecb61310bc411","port":0}]
}
},
{
"id":"0c74efbb9a85bee5",
"type":"function",
"z":"914734122ce79fcd",
"name":"create service call",
"func":"msg._originalPayload = msg.payload;\nlet flow_msg_variables = {\n tag: '',\n service: '',\n message: msg,\n date_created: Date.now()\n}\n\n//flow.set('latestMessage', msg);\n\nvar xTitle = \"\";\nvar xSubtitle = \"\";\nvar xMessage = \"\";\nvar xServices = \"\";\nvar xTag = \"\";\nvar xUrl = \"\";\n// overrides\nif (typeof msg.notificationOverride !== 'undefined' && msg.notificationOverride !== null) {\n if (typeof msg.notificationOverride.title !== 'undefined' && msg.notificationOverride.title !=='' && msg.notificationOverride.title !== null){\n xTitle = msg.notificationOverride.title;\n } else {\n xTitle = env.get('title');\n }\n if (typeof msg.notificationOverride.subtitle !== 'undefined' && msg.notificationOverride.subtitle !=='' && msg.notificationOverride.subtitle !== null){\n xSubtitle = msg.notificationOverride.subtitle;\n } else {\n xSubtitle = env.get('subtitle');\n }\n if (typeof msg.notificationOverride.message !== 'undefined' && msg.notificationOverride.message !=='' && msg.notificationOverride.message !== null){\n xMessage = msg.notificationOverride.message;\n } else {\n xMessage = env.get('message');\n }\n if (typeof msg.notificationOverride.url !== 'undefined' && msg.notificationOverride.url !=='' && msg.notificationOverride.url !== null){\n xUrl = msg.notificationOverride.url;\n } else {\n xUrl = env.get('notificationUrl');\n }\n if (typeof msg.notificationOverride.services !== 'undefined' && msg.notificationOverride.services !=='' && msg.notificationOverride.services !== null){\n xServices = msg.notificationOverride.services;\n } else {\n xServices = env.get('service');\n }\n// flow.set('service', xServices);\n flow_msg_variables.service=xServices;\n if (typeof msg.notificationOverride.tag !== 'undefined' && msg.notificationOverride.tag !=='' && msg.notificationOverride.tag !== null){\n xTag = msg.notificationOverride.tag.replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase();\n } else {\n if (env.get('tag') !== '') {\n xTag = `${env.get('tag').replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase()}`;\n } else {\n // need to still set this to something in case clear_notification is sent.\n xTag = `${env.get('title').replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase()}_${flow.get('random')}`;\n }\n }\n//support multiple tags per flow\n //flow.set('tag',xTag);\n flow_msg_variables.tag=xTag;\n} else {\n // If no override is sent in...\n if (env.get('tag') !== '') {\n xTag = `${env.get('tag').replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase()}`;\n } else {\n // need to still set this to something in case clear_notification is sent.\n xTag = `${env.get('title').replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase()}_${flow.get('random')}`;\n }\n//support multiple tags per flow\n// flow.set('tag',xTag);\n flow_msg_variables.tag=xTag;\n \n xServices = env.get('service');\n// flow.set('service', xServices);\n flow_msg_variables.service=xServices;\n \n xTitle = env.get('title');\n xSubtitle = env.get('subtitle');\n xMessage = env.get('message');\n xUrl = env.get('notificationUrl');\n}\nlet all_flow_messages= flow.get('flow_messages');\nif (!all_flow_messages){\n all_flow_messages=[];\n}\nlet new_flow_messages=[];\nfor(var i=0;i<all_flow_messages.length;i++){//copy (and reset) the messages array\n if ((all_flow_messages[i].tag==flow_msg_variables.tag)&&(all_flow_messages[i].service==flow_msg_variables.service)){\n continue;//don't copy this message\n }else{\n if (Date.now()-all_flow_messages[i].date_created<86400000){//only copy messages less than 24h old\n new_flow_messages.push(all_flow_messages[i]);\n }\n }\n}\nnew_flow_messages.push(flow_msg_variables);\nflow.set('flow_messages',new_flow_messages);\n\nconst services = xServices;//flow.get('service');\nif(!services) {\n node.status({\n text: 'no services defined',\n shape: 'ring',\n fill: 'red'\n });\n return; \n} else if (services == \"NOONE\"){\n node.status({\n text: 'No one to send to',\n shape: 'ring',\n fill: 'yellow'\n });\n return;\n}\n\n// create actions\nconst actions = [];\n[1,2,3,4].forEach(i => {\n const name = `action${i}`\n if (env.get(`${name}Title`) !== ''){\n const action = env.get(`${name}Title`).replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase();\n const title = env.get(`${name}Title`);\n const activationMode = env.get(`${name}ActivationMode`); \n \n const uri = env.get(`${name}Uri`);\n const textInputButtonTitle = env.get(`${name}TextInputButtonTitle`);\n const textInputPlaceholder = env.get(`${name}TextInputPlaceHolder`);\n const authenticationRequired = env.get(`${name}AuthenticationRequired`);\n const destructive = env.get(`${name}Destructive`);\n const behavior = env.get(`${name}Behavior`);\n const icon = env.get(`${name}Icon`);\n \n const actionObject = {};\n actionObject.action = action;\n actionObject.title = title;\n actionObject.activationMode = activationMode;\n \n if (uri != \"\") actionObject.uri = uri;\n if (textInputButtonTitle != \"\") actionObject.textInputButtonTitle = textInputButtonTitle;\n if (textInputPlaceholder != \"\") actionObject.textInputPlaceholder = textInputPlaceholder;\n if (authenticationRequired != \"\") actionObject.authenticationRequired = authenticationRequired;\n if (destructive != \"\") actionObject.destructive = destructive;\n if (behavior != \"\") actionObject.behavior = behavior;\n if (icon != \"\") actionObject.icon = icon;\n \n actions.push(actionObject);\n }\n});\n// create msg object\nmsg.payload = {\n domain: 'notify',\n data: {\n title: xTitle,\n message: xMessage,\n data: {\n push: {},\n tag: xTag\n }\n }\n };\nif (actions.length > 0) {\n msg.payload.data.data.action_data = {tag: xTag};\n msg.payload.data.data.actions = actions;\n}\n// notification url\nif (xUrl !== \"\") {\n msg.payload.data.data.url = {};\n msg.payload.data.data.url = xUrl;\n}\n// subtitle\nif (xSubtitle !== '') {\n msg.payload.data.data.subtitle = xSubtitle;\n}\n// sound information\nmsg.payload.data.data.push.sound = {};\n\nif (env.get('customSound').length > 0){\n msg.payload.data.data.push.sound.name = env.get('customSound');\n} else if (env.get('customSoundPreInstalled').length > 0) {\n if(env.get('customSoundPreInstalled')=='none'){\n msg.payload.data.data.push.sound = 'none';\n }else{\n msg.payload.data.data.push.sound.name = env.get('customSoundPreInstalled');\n }\n} else {\n msg.payload.data.data.push.sound.name = 'default';\n}\n\n//if (env.get('isCriticalNotification')) {\n// msg.payload.data.data.push.sound.critical = 1;\n// msg.payload.data.data.push.sound.volume = 1.0;\n//}\nmsg.payload.data.data.push[\"interruption-level\"] = env.get('interruptionLevel');\n// group thread id\nif (env.get('group') !== '') {\n msg.payload.data.data.group = env.get('group');\n}\n\n// Map Information\nif (env.get('latitudeFirst') !== 0 && env.get('longitudeFirst') !== 0){\n msg.payload.data.data.action_data.latitude = env.get('latitudeFirst');\n msg.payload.data.data.action_data.longitude = env.get('longitudeFirst');\n if (env.get('latitudeSecond') !== 0 && env.get('longitudeSecond') !== 0){\n msg.payload.data.data.action_data.second_latitude = env.get('latitudeSecond');\n msg.payload.data.data.action_data.second_longitude = env.get('longitudeSecond');\n // add in all the extras, which default to false.\n msg.payload.data.data.action_data.shows_line_between_points = env.get('showLineBetweenPoints');\n msg.payload.data.data.action_data.shows_compass = env.get('showCompass');\n msg.payload.data.data.action_data.shows_points_of_interest = env.get('showPointsOfInterest');\n msg.payload.data.data.action_data.shows_scale = env.get('showScale');\n msg.payload.data.data.action_data.shows_traffic = env.get('showTraffic');\n msg.payload.data.data.action_data.shows_user_location = env.get('showUserLocation');\n }\n}\n// camera information\nif (env.get('cameraEntity') !== '') {\n msg.payload.data.data.entity_id = env.get('cameraEntity');\n}\n// media information\nif (env.get('contentUrl') !== '') {\n\n} else {\n if (env.get('imagePath') !== '') {\n msg.payload.data.data.image = env.get('imagePath');\n }\n if (env.get('videoPath') !== '') {\n msg.payload.data.data.video = env.get('videoPath');\n }\n if (env.get('audioPath') !== '') {\n msg.payload.data.data.audio = env.get('audioPath');\n }\n}\nif (env.get('contentUrl') !== '' || env.get('imagePath') !== '' || env.get('videoPath') !== '' || env.get('audioPath') !== '') {\n if (env.get('lazyLoading')) {\n msg.payload.data.data.lazy = env.get('lazyLoading');\n }\n if (env.get('hideThumbnail')) {\n msg.payload.data.data.attachment = {};\n msg.payload.data.data.attachment['hide-thumbnail'] = env.get('hideThumbnail');\n }\n}\nservices.trim().split(/,\\s*/).forEach(service => {\n if(!service) return;\n msg.payload.service = service;\n node.send(msg);\n});\n\nnode.done();",
"outputs":1,
"noerr":0,
"initialize":"flow.set('random',Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5).toUpperCase());\n",
"finalize":"",
"libs":[],
"x":530,
"y":40,
"wires":[["623033ccf4ee0715"]]
},
{
"id":"7bb055c340123ca6",
"type":"switch",
"z":"914734122ce79fcd",
"name":"which action?",
"property":"responseIndex",
"propertyType":"flow",
"rules":[
{"t":"eq","v":"1","vt":"num"},
{"t":"eq","v":"2","vt":"num"},
{"t":"eq","v":"3","vt":"num"},
{"t":"eq","v":"4","vt":"num"}
],
"checkall":"true",
"repair":false,
"outputs":4,
"x":1260,
"y":220,
"wires":[[],[],[],[]]
},
{
"id":"f87ecb61310bc411",
"type":"status",
"z":"914734122ce79fcd",
"name":"",
"scope":[
"0c74efbb9a85bee5",
"6cdec7ddd37347ca",
"d5bbdcb0c9aae966",
"a18477a92277fde6"
],
"x":80,
"y":320,
"wires":[[]]
},
{
"id":"6cdec7ddd37347ca",
"type":"function",
"z":"914734122ce79fcd",
"name":"build message",
"func":"const latestMessage = flow.get('latestMessage');\nconst event = msg.payload.event;\n\nlatestMessage.payload = latestMessage._originalPayload;\nlatestMessage.eventData = msg.payload;\ndelete latestMessage._originalPayload;\n\nif(env.get('userInfo')) {\n const userData = msg.userData.find(u => u.id === msg.payload.context.user_id);\n latestMessage.userData = userData;\n}\n\n\ntry{ //For Some reason it is called twice, second time with empty env.get values\n const index = [1,2,3,4].find(i => env.get(`action${i}Title`).replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase() === event.actionName);\n flow.set(\"responseIndex\",index);\n}catch(e){}\ntry{\n node.status({\n text: `${env.get(`action${index}Title`).replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase()} at: ${getPrettyDate()}`,\n shape: 'dot',\n fill: 'green'\n });\n}catch(e){}\nreturn latestMessage;\n\n\nfunction getPrettyDate() {\n return new Date().toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n hour12: false,\n hour: 'numeric',\n minute: 'numeric',\n });\n}",
"outputs":1,
"noerr":0,
"initialize":"",
"finalize":"",
"libs":[],
"x":1060,
"y":220,
"wires":[["7bb055c340123ca6"]]
},
{
"id":"315c4ad3c3647075",
"type":"switch",
"z":"914734122ce79fcd",
"name":"belongs here?",
"property":"payload.event.action_data.tag",
"propertyType":"msg",
"rules":[{"t":"eq","v":"tag","vt":"flow"}],
"checkall":"true",
"repair":false,
"outputs":1,
"x":380,
"y":260,
"wires":[[]]
},
{
"id":"95c45e1dfd4436e0",
"type":"ha-api",
"z":"914734122ce79fcd",
"name":"get user info",
"server":"",
"version":1,
"debugenabled":false,
"protocol":"websocket",
"method":"get",
"path":"",
"data":"{\"type\": \"config/auth/list\"}",
"dataType":"json",
"responseType":"json",
"outputProperties":[
{
"property":"userData",
"propertyType":"msg",
"value":"",
"valueType":"results"
}
],
"x":850,
"y":260,
"wires":[["6cdec7ddd37347ca"]]
},
{
"id":"52754e832dea9cb6",
"type":"switch",
"z":"914734122ce79fcd",
"name":"fetch user info?",
"property":"userInfo",
"propertyType":"env",
"rules":[{"t":"true"},{"t":"else"}],
"checkall":"true",
"repair":false,
"outputs":2,
"x":840,
"y":220,
"wires":[
["95c45e1dfd4436e0"],
["6cdec7ddd37347ca"]
]
},
{
"id":"66cdad51e119544d",
"type":"server-events",
"z":"914734122ce79fcd",
"name":"ios.notification_action_fired",
"server":"",
"version":1,
"event_type":"ios.notification_action_fired",
"exposeToHomeAssistant":false,
"haConfig":[
{"property":"name","value":""},
{"property":"icon","value":""}
],
"waitForRunning":false,
"outputProperties":[
{
"property":"payload",
"propertyType":"msg",
"value":"",
"valueType":"eventData"
},
{
"property":"topic",
"propertyType":"msg",
"value":"$outputData(\"eventData\").event_type",
"valueType":"jsonata"
},
{
"property":"event_type",
"propertyType":"msg",
"value":"$outputData(\"eventData\").event_type",
"valueType":"jsonata"
}
],
"x":130,
"y":180,
"wires":[["1d74d403fab61ed8"]]
},
{
"id":"d5bbdcb0c9aae966",
"type":"api-call-service",
"z":"914734122ce79fcd",
"name":"Send Notifications",
"server":"",
"version":5,
"debugenabled":false,
"domain":"notify",
"service":"",
"areaId":[],
"deviceId":[],
"entityId":[],
"data":"",
"dataType":"json",
"mergeContext":"callServiceData",
"mustacheAltTags":false,
"outputProperties":[],
"queue":"none",
"x":1130,
"y":40,
"wires":[[]]
},
{
"id":"a18477a92277fde6",
"type":"function",
"z":"914734122ce79fcd",
"name":"create CLEAR service call",
"func":"msg._originalPayload = msg.payload;\n//flow.set('latestMessage', msg);\nvar tag_to_clear = \"\";\nvar services = \"\";\nvar clearAll = false;\nif (typeof msg.notificationOverride !== 'undefined') {\n if (typeof msg.notificationOverride.clear !== 'undefined' && msg.notificationOverride.clear !== null && msg.notificationOverride.clear) {\n clearAll = true;\n }\n if (typeof msg.notificationOverride.services !== 'undefined' && msg.notificationOverride.services !== null && msg.notificationOverride.services){\n services = msg.notificationOverride.services;\n }\n if (typeof msg.notificationOverride.tag !== 'undefined' && msg.notificationOverride.tag !== null && msg.notificationOverride.tag){\n tag_to_clear = msg.notificationOverride.tag.replace(/[^\\w\\s]/gi, '').replace(/\\s+/g,'_').toUpperCase();//formatting tags as sent to the phone before\n }\n}\nif (tag_to_clear==\"\"){//no specific tag sent, clear the last message.\n var all_flow_messages= flow.get('flow_messages');\n if(all_flow_messages) {\n var last_message= all_flow_messages.pop();\n if (last_message){//on nodeRED restart\n tag_to_clear= last_message.tag;\n services = last_message.service;//override service to the one used in last message sent\n flow.set('flow_messages',all_flow_messages);//clear the message from memory\n }\n }\n}\n\nif(services==\"\") {\n node.status({\n text: 'no services defined',\n shape: 'ring',\n fill: 'red'\n });\n return; \n}\nif(tag_to_clear==\"\") {\n node.status({\n text: 'no messages to delete',\n shape: 'ring',\n fill: 'red'\n });\n return; \n}\n// create ios msg object\nmsg.payload = {\n domain: 'notify',\n data: {\n message: \"clear_notification\",\n data: {\n tag: tag_to_clear //flow.get('tag'),\n }\n }\n };\n\nfunction getPrettyDate() {\n return new Date().toLocaleDateString('en-US', {\n month: 'short',\n day: 'numeric',\n hour12: false,\n hour: 'numeric',\n minute: 'numeric',\n });\n}\n\nif (clearAll){\n delete msg.notificationOverride;\n}\n \nvar xCountCleared = 0;\nservices.trim().split(/,\\s*/).forEach(service => {\n if(!service) return;\n // only clear on devices that didn't send the event.\n if (clearAll){\n msg.payload.service = service;\n node.send(msg);\n xCountCleared++;\n } else if (!service.includes(msg._originalPayload.event.sourceDeviceID)){\n msg.payload.service = service;\n node.send(msg);\n xCountCleared++;\n }\n});\nif (xCountCleared > 0) {\n node.status({\n text: `${xCountCleared} messages cleared at: ${getPrettyDate()}`,\n shape: 'dot',\n fill: 'blue'\n });\n} else {\n node.status({\n text: `No messages cleared: ${getPrettyDate()}`,\n shape: 'dot',\n fill: 'red'\n });\n}",
"outputs":1,
"noerr":0,
"initialize":"",
"finalize":"",
"libs":[],
"x":550,
"y":80,
"wires":[["b649a0d3bf05a394"]]
},
{
"id":"2f18a199fe3023b9",
"type":"switch",
"z":"914734122ce79fcd",
"name":"Clear Notification on Action?",
"property":"isClearNotificationsOnAction",
"propertyType":"env",
"rules":[{"t":"true"},{"t":"false"}],
"checkall":"true",
"repair":false,
"outputs":2,
"x":420,
"y":220,
"wires":[
["a18477a92277fde6","ca88e6add3be35fc"],
["52754e832dea9cb6"]
]
},
{
"id":"59d66e6372aaca66",
"type":"api-call-service",
"z":"914734122ce79fcd",
"name":"Clear Notifications",
"server":"",
"version":5,
"debugenabled":false,
"domain":"notify",
"service":"",
"areaId":[],
"deviceId":[],
"entityId":[],
"data":"",
"dataType":"json",
"mergeContext":"callServiceData",
"mustacheAltTags":false,
"outputProperties":[],
"queue":"none",
"x":1130,
"y":80,
"wires":[[]]
},
{
"id":"ca88e6add3be35fc",
"type":"delay",
"z":"914734122ce79fcd",
"name":"",
"pauseType":"delay",
"timeout":"10",
"timeoutUnits":"seconds",
"rate":"1",
"nbRateUnits":"1",
"rateUnits":"second",
"randomFirst":"1",
"randomLast":"5",
"randomUnits":"seconds",
"drop":false,
"outputs":1,
"x":660,
"y":220,
"wires":[["52754e832dea9cb6"]]
},
{
"id":"f8d958779acdc007",
"type":"switch",
"z":"914734122ce79fcd",
"name":"clear?",
"property":"notificationOverride.clear",
"propertyType":"msg",
"rules":[
{
"t":"istype",
"v":"undefined",
"vt":"undefined"
},
{"t":"null"},
{"t":"false"},
{"t":"true"}
],
"checkall":"false",
"repair":false,
"outputs":4,
"x":170,
"y":60,
"wires":[
["0c74efbb9a85bee5"],
["0c74efbb9a85bee5"],
["0c74efbb9a85bee5"],
["a18477a92277fde6"]
]
},
{
"id":"b649a0d3bf05a394",
"type":"delay",
"z":"914734122ce79fcd",
"name":"",
"pauseType":"rate",
"timeout":"5",
"timeoutUnits":"seconds",
"rate":"1",
"nbRateUnits":"1",
"rateUnits":"second",
"randomFirst":"1",
"randomLast":"5",
"randomUnits":"seconds",
"drop":false,
"outputs":1,
"x":910,
"y":80,
"wires":[["59d66e6372aaca66"]]
},
{
"id":"623033ccf4ee0715",
"type":"delay",
"z":"914734122ce79fcd",
"name":"",
"pauseType":"rate",
"timeout":"5",
"timeoutUnits":"seconds",
"rate":"1",
"nbRateUnits":"1",
"rateUnits":"second",
"randomFirst":"1",
"randomLast":"5",
"randomUnits":"seconds",
"drop":false,
"allowrate":false,
"outputs":1,
"x":910,
"y":40,
"wires":[["d5bbdcb0c9aae966"]]
},
{
"id":"1d74d403fab61ed8",
"type":"function",
"z":"914734122ce79fcd",
"name":"belongs here?",
"func":"let msg_tag=msg.payload.event.action_data.tag;\nlet all_flow_messages= flow.get('flow_messages');\n//node.warn({'message tag':msg_tag,'flow_messages':all_flow_messages});\nif(all_flow_messages){\n for (var i=0;i<all_flow_messages.length;i++){\n if (all_flow_messages[i].tag.trim()==msg_tag.trim()){\n//node.warn(all_flow_messages[i])\n flow.set('latestMessage',all_flow_messages[i].message);\n return [msg,null];\n }\n }\n}\nreturn [null,msg];\n",
"outputs":2,
"noerr":0,
"initialize":"",
"finalize":"",
"libs":[],
"x":380,
"y":180,
"wires":[["2f18a199fe3023b9"],[]]
}
]
@sstratoti
Copy link

Thank you thank you thank you for the updates with regards to tags and clearing messages. Great Job!!

@sstratoti
Copy link

So I mentioned this in my gist, but I've created a github project for this. I think it'll be easier than us all managing our own gists. I'd welcome any more updates you'd like to submit a PR for!

I've gone through the past few hours and have diff'd our code to see all of your updates. Very well done! I've run some test cases through my node red, and I think we're looking good for your changes getting merged in. I've made a couple updates myself as well that I hadn't updated in the gist quite yet.

New Github Project: https://github.com/sstratoti/actionable-notifications-subflow-for-ios

Also, just a heads up - the subflow ID in your gist is different than the one in mine. So if a user wanted to use yours and import it, they'd have to change all of their existing nodes to use the new id (or if they're not familiar how to do that, they may have to replace all of the older subflows with yours). If they import with the id I've been using, it'll ask if they want to "replace" over top of it. It makes updating easier. That, and you may want to use this tool: https://zachowj.github.io/node-red-contrib-home-assistant-websocket/scrubber/ to scrub out your HA connection data.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment