16 Commits

Author SHA1 Message Date
8dd7771eee Remove deprecated service calls
home_automation/HA-NerdFlows#28
2025-03-21 01:28:23 -04:00
c63adaa68d Make area weather alerts reusable as a subflow 2025-03-20 00:33:31 -04:00
3c092bf519 Rename Defiance file for use as local alerts template 2025-03-20 00:04:59 -04:00
19e0e35bf4 Add watches for Defiance 2025-03-19 18:18:35 -04:00
b9a296d312 Improve filter phrases for warnings 2025-03-19 17:56:47 -04:00
503776de4a Add stats for considerable destructive t-storm, confirmed tornado 2025-03-19 17:11:17 -04:00
e37e4d7718 Clean-up severe thunderstorm and tornado alert presentation 2025-03-18 01:13:27 -04:00
2a5aa26e5c Functions for general alerts and Defiance-specific alerts 2025-03-17 01:35:05 -04:00
96c4918d76 Function for filtering weather alerts 2025-03-16 03:59:03 -04:00
b4fbc2f5e6 Continue improving basement heater logic, as the weather warms up 2025-03-11 13:36:49 -04:00
e53e6ab5f2 Improve logic for when basement heater is needed 2025-03-11 02:00:49 -04:00
4a8a9e10de Add function code from "work tomorrow" sensor flow 2025-03-09 14:22:19 -04:00
b628a0b197 Update .gitignore 2025-03-01 00:53:27 -05:00
0f6b6a8275 Fix timer not being canceled when motion is detected again 2025-02-23 22:54:49 -05:00
e23c78c971 Improve motion lighting in some rooms
Motion lighting should no longer reset lights to adaptive when scene or brightness has been changed manually
2025-02-23 01:07:31 -05:00
87ed0e89c0 Use temperature-based preset for basement heater 2025-02-17 06:19:25 -05:00
19 changed files with 396 additions and 840 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
/.vscode **.vscode

View File

@ -13,7 +13,7 @@ if (outsideTemp > 32) {
if (nightMode === 'on') { if (nightMode === 'on') {
preset = "frost" preset = "frost"
} else { } else {
preset = "eco" preset = "activity"
} }
} }

View File

@ -0,0 +1,33 @@
const states = global.get('homeassistant.homeAssistant.states')
const allowed = states['input_boolean.basement_studio_heat_allowed'].state
const outsideTemp = states['weather.iron_nerd_weather_station'].attributes.temperature
const todaysHighTemp = states['sensor.todays_high_temp'].state
const basementTemp = states['sensor.basement_studio_temperature'].state
let power = {}
let reason = {}
if (todaysHighTemp < 55) {
power = 'on'
reason = 'Todays High Temperature'
} else if (outsideTemp < 40) {
power = 'on'
reason = 'Outside Temperature'
} else if (basementTemp < 64) {
power = 'on'
reason = 'Basement Temperature'
} else {
power = 'off'
}
if (allowed === 'on') {
if (power === 'on') {
node.status({fill:'green',shape:'dot',text:'Heater Needed: ' + reason})
node.send(msg,null)
} else {
node.status({fill:'red',shape:'ring',text:'Heater Not Needed'})
node.send(null,msg)
}
} else {
node.status({fill:'red',shape:'ring',text:'Heat Disabled'})
}

View File

@ -53,8 +53,7 @@ node.log("Kallen Bedroom: Decision Logic Complete")
let sendFan = { let sendFan = {
"payload": { "payload": {
"domain": "fan", "action": "fan." + setFan,
"service": setFan,
"target": { "target": {
"entity_id": ["fan.kallen_bedroom_fan"] "entity_id": ["fan.kallen_bedroom_fan"]
}, },
@ -64,8 +63,7 @@ let sendFan = {
let sendWhiteNoise = { let sendWhiteNoise = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + setWhiteNoise,
"service": setWhiteNoise,
"target": { "target": {
"entity_id": ["input_boolean.white_noise_kallen_bedroom"] "entity_id": ["input_boolean.white_noise_kallen_bedroom"]
}, },
@ -75,8 +73,7 @@ let sendWhiteNoise = {
let sendVolume = { let sendVolume = {
"payload": { "payload": {
"domain": "media_player", "action": "media_player.volume_set",
"service": "volume_set",
"target": { "target": {
"entity_id": ["media_player.kallen_bedroom_google_speaker"] "entity_id": ["media_player.kallen_bedroom_google_speaker"]
}, },
@ -88,8 +85,7 @@ let sendVolume = {
let sendLights = { let sendLights = {
"payload": { "payload": {
"domain": "light", "action": "light." + setLights,
"service": setLights,
"target": { "target": {
"entity_id": ["light.kallen_bedroom_lights"] "entity_id": ["light.kallen_bedroom_lights"]
}, },
@ -99,8 +95,7 @@ let sendLights = {
let sendWake = { let sendWake = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + setWake,
"service": setWake,
"target": { "target": {
"entity_id": ["input_boolean.kallen_awake"] "entity_id": ["input_boolean.kallen_awake"]
}, },

View File

@ -12,8 +12,7 @@ let setFan = 'turn_off'
let sendFan = { let sendFan = {
"payload": { "payload": {
"domain": "fan", "action": "fan." + setFan,
"service": setFan,
"target": { "target": {
"entity_id": ["fan.master_bedroom_fan"] "entity_id": ["fan.master_bedroom_fan"]
}, },
@ -23,8 +22,7 @@ let sendFan = {
let sendHvac = { let sendHvac = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_hvac_mode",
"service": "set_hvac_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -36,8 +34,7 @@ let sendHvac = {
let sendTemp = { let sendTemp = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_temperature",
"service": "set_temperature",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -49,8 +46,7 @@ let sendTemp = {
let sendEco = { let sendEco = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_preset_mode",
"service": "set_preset_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -62,8 +58,7 @@ let sendEco = {
let sendAcFan = { let sendAcFan = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_fan_mode",
"service": "set_fan_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },

View File

@ -183,8 +183,7 @@ node.log("Master Bedroom Climate: Decision Logic Complete")
let sendFan = { let sendFan = {
"payload": { "payload": {
"domain": "fan", "action": "fan." + setFan,
"service": setFan,
"target": { "target": {
"entity_id": ["fan.master_bedroom_fan"] "entity_id": ["fan.master_bedroom_fan"]
}, },
@ -194,8 +193,7 @@ let sendFan = {
let sendCool = { let sendCool = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + setCool,
"service": setCool,
"target": { "target": {
"entity_id": ["input_boolean.master_bedroom_cooling_on"] "entity_id": ["input_boolean.master_bedroom_cooling_on"]
}, },
@ -205,8 +203,7 @@ let sendCool = {
let sendSleep = { let sendSleep = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + setSleep,
"service": setSleep,
"target": { "target": {
"entity_id": ["input_boolean.master_bedroom_sleeping"] "entity_id": ["input_boolean.master_bedroom_sleeping"]
}, },
@ -216,8 +213,7 @@ let sendSleep = {
let sendPeople = { let sendPeople = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + setPeople,
"service": setPeople,
"target": { "target": {
"entity_id": ["input_boolean.tony_awake","input_boolean.tina_awake"] "entity_id": ["input_boolean.tony_awake","input_boolean.tina_awake"]
}, },
@ -227,8 +223,7 @@ let sendPeople = {
let sendDisplay = { let sendDisplay = {
"payload": { "payload": {
"domain": "switch", "action": "switch." + setDisplay,
"service": setDisplay,
"target": { "target": {
"entity_id": ["switch.master_bedroom_aircon_display"] "entity_id": ["switch.master_bedroom_aircon_display"]
}, },
@ -245,16 +240,14 @@ let notify = {
let sendBriefing = { let sendBriefing = {
"payload": { "payload": {
"domain": "script", "action": "script." + setBriefing,
"service": setBriefing
}, },
"delay": setBriefingDelay "delay": setBriefingDelay
} }
let sendHvac = { let sendHvac = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_hvac_mode",
"service": "set_hvac_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -266,8 +259,7 @@ let sendHvac = {
let sendTemp = { let sendTemp = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_temperature",
"service": "set_temperature",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -279,8 +271,7 @@ let sendTemp = {
let sendEco = { let sendEco = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_preset_mode",
"service": "set_preset_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -292,8 +283,7 @@ let sendEco = {
let sendAcFan = { let sendAcFan = {
"payload": { "payload": {
"domain": "climate", "action": "climate.set_fan_mode",
"service": "set_fan_mode",
"target": { "target": {
"entity_id": ["climate.master_bedroom_aircon"] "entity_id": ["climate.master_bedroom_aircon"]
}, },
@ -305,8 +295,7 @@ let sendAcFan = {
let sendEchoDotDND = { let sendEchoDotDND = {
"payload": { "payload": {
"domain": "switch", "action": "switch." + echoDotService,
"service": echoDotService,
"target": { "target": {
"entity_id": ["switch.basement_echo_dot_do_not_disturb_switch"] "entity_id": ["switch.basement_echo_dot_do_not_disturb_switch"]
}, },

View File

@ -7,17 +7,22 @@ const payload = msg.payload
const newDuration = duration * 60 const newDuration = duration * 60
if (payload === 'on') { if (payload === 'on') {
if (lux <= threshold || lights === 'on') { if (lux <= threshold && lights === 'off') {
node.status({fill:'green',shape:'dot',text:'Lights On'}) node.status({fill:'green',shape:'dot',text:'Turning lights on'})
node.send([msg,null]) node.send([msg,msg,null])
} else { } else {
node.status({fill:'red',shape:'ring',text:'Too bright'}) if (lights === 'on') {
node.status({fill:'red',shape:'ring',text:'Lights already on'})
node.send([null,msg,null])
} else {
node.status({fill:'red',shape:'ring',text:'Too bright'})
}
} }
} else if (payload === 'off') { } else if (payload === 'off') {
if (lights === 'on') { if (lights === 'on') {
msg.duration = newDuration msg.duration = newDuration
node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'}) node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'})
node.send([null,msg]) node.send([null,null,msg])
} else { } else {
node.status({fill:"red",shape:"ring",text:"Lights already off"}) node.status({fill:"red",shape:"ring",text:"Lights already off"})
} }

View File

@ -1,5 +1,6 @@
const states = global.get('homeassistant.homeAssistant.states') const states = global.get('homeassistant.homeAssistant.states')
const lights = states['light.mud_room_overhead'].state const lights = states['light.mud_room_overhead'].state
const selScene = states['input_text.mud_room_selected_scene'].state
const duration = states['input_number.mud_room_lights_off_delay'].state const duration = states['input_number.mud_room_lights_off_delay'].state
const lux = parseInt(states['sensor.mud_room_illuminance'].state) const lux = parseInt(states['sensor.mud_room_illuminance'].state)
const threshold = parseInt(states['input_number.mud_room_lux_threshold'].state) const threshold = parseInt(states['input_number.mud_room_lux_threshold'].state)
@ -7,17 +8,22 @@ const payload = msg.payload
const newDuration = duration * 60 const newDuration = duration * 60
if (payload === 'on') { if (payload === 'on') {
if (lux <= threshold || lights === 'on') { if (lux <= threshold && (lights === 'off' || selScene === 'Nightlight')) {
node.status({fill:'green',shape:'dot',text:'Lights On'}) node.status({fill:'green',shape:'dot',text:'Turning lights on'})
node.send([msg,null]) node.send([msg,msg,null])
} else { } else {
node.status({fill:'red',shape:'ring',text:'Too bright'}) if (lights === 'on') {
node.status({fill:'red',shape:'ring',text:'Lights already on'})
node.send([null,msg,null])
} else {
node.status({fill:'red',shape:'ring',text:'Too bright'})
}
} }
} else if (payload === 'off') { } else if (payload === 'off') {
if (lights === 'on') { if (lights === 'on') {
msg.duration = newDuration msg.duration = newDuration
node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'}) node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'})
node.send([null,msg]) node.send([null,null,msg])
} else { } else {
node.status({fill:"red",shape:"ring",text:"Lights already off"}) node.status({fill:"red",shape:"ring",text:"Lights already off"})
} }

View File

@ -68,8 +68,7 @@ if (payload === 'start') {
// Prepare message payloads // Prepare message payloads
let sendTimerStart = { let sendTimerStart = {
"payload": { "payload": {
"domain": "timer", "action": "timer.start",
"service": "start",
"target": { "target": {
"entity_id": timerEntity "entity_id": timerEntity
}, },
@ -81,8 +80,7 @@ let sendTimerStart = {
let sendTimerCancel = { let sendTimerCancel = {
"payload": { "payload": {
"domain": "timer", "action": "timer.cancel",
"service": "cancel",
"target": { "target": {
"entity_id": timerEntity "entity_id": timerEntity
}, },
@ -92,8 +90,7 @@ let sendTimerCancel = {
let sendBoolFinished = { let sendBoolFinished = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean." + servFinished,
"service": servFinished,
"target": { "target": {
"entity_id": boolFinished "entity_id": boolFinished
}, },
@ -103,8 +100,7 @@ let sendBoolFinished = {
let sendDateTimeFinished = { let sendDateTimeFinished = {
"payload": { "payload": {
"domain": "input_datetime", "action": "input_datetime.set_datetime",
"service": "set_datetime",
"target": { "target": {
"entity_id": dateTimeEntity "entity_id": dateTimeEntity
}, },

View File

@ -10,13 +10,6 @@ const segLivingRoom2 = [10,11,12,13,14,15,16,17,18,19]
const segLivingRoom3 = [20,21,22,23,24,25,26,27,28,29] const segLivingRoom3 = [20,21,22,23,24,25,26,27,28,29]
const segLivingRoom4 = [30,31,32,33,34,35,36,37,38,39] const segLivingRoom4 = [30,31,32,33,34,35,36,37,38,39]
// Preset effect segments for living room LED strip
const effectSegLivingRoom1 = [].concat(segLivingRoom1, segLivingRoom3)
const effectSegLivingRoom2 = [].concat(segLivingRoom2, segLivingRoom4)
// Full strip for living room LED strip
const livingRoomFull = [].concat(halfLivingRoom1, halfLivingRoom2)
// Half and half for basement LED strip // Half and half for basement LED strip
const halfBasement1 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] const halfBasement1 = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15]
const halfBasement2 = [16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31] const halfBasement2 = [16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31]
@ -27,65 +20,18 @@ const segBasement2 = [8,9,10,11,12,13,14,15]
const segBasement3 = [16,17,18,19,20,21,22,23] const segBasement3 = [16,17,18,19,20,21,22,23]
const segBasement4 = [24,25,26,27,28,29,30,31] const segBasement4 = [24,25,26,27,28,29,30,31]
// Preset effect segments for basement LED strip
const effectSegBasement1 = [].concat(segBasement1, segBasement3)
const effectSegBasement2 = [].concat(segBasement2, segBasement4)
// Full strip for basement LED strip
const basementFull = [].concat(halfBasement1, halfBasement2)
// Adaptive Lighting switches
const adaptiveFirstFloor = [
"switch.adaptive_lighting_living_room",
"switch.adaptive_lighting_dining_room_lamp",
"switch.adaptive_lighting_tina_lamp"]
const adaptiveBasement = [
"switch.adaptive_lighting_basement_studio"
]
// Define light arrays for backup scenes
const lightsTinaDesk = ['light.tina_desk_strip','light.tina_lamp_top','light.tina_lamp_side']
const lightsBasement = ['light.basement_tall_lamp','light.basement_short_lamp','light.basement_stairwell','light.basement_led_strip_1']
const lightsLivingRoom = ['light.living_room_color_1','light.living_room_color_2','light.living_room_color_3','light.living_room_led_strip']
const lightsDiningRoom = ['light.dining_room_lamp']
const lightsStairwell = ['light.stairwell_led_strip']
// Write flow variables
flow.set("halfLivingRoom1", halfLivingRoom1, "diskCon") flow.set("halfLivingRoom1", halfLivingRoom1, "diskCon")
flow.set("halfLivingRoom2", halfLivingRoom2, "diskCon") flow.set("halfLivingRoom2", halfLivingRoom1, "diskCon")
flow.set("segLivingRoom1", segLivingRoom1, "diskCon") flow.set("segLivingRoom1", segLivingRoom1, "diskCon")
flow.set("segLivingRoom2", segLivingRoom2, "diskCon") flow.set("segLivingRoom2", segLivingRoom2, "diskCon")
flow.set("segLivingRoom3", segLivingRoom3, "diskCon") flow.set("segLivingRoom3", segLivingRoom3, "diskCon")
flow.set("segLivingRoom4", segLivingRoom4, "diskCon") flow.set("segLivingRoom4", segLivingRoom4, "diskCon")
flow.set("effectSegLivingRoom1", effectSegLivingRoom1, "diskCon")
flow.set("effectSegLivingRoom2", effectSegLivingRoom2, "diskCon")
flow.set("livingRoomFull", livingRoomFull, "diskCon")
flow.set("halfBasement1", halfBasement1, "diskCon") flow.set("halfBasement1", halfBasement1, "diskCon")
flow.set("halfBasement2", halfBasement2, "diskCon") flow.set("halfBasement2", halfBasement1, "diskCon")
flow.set("segBasement1", segBasement1, "diskCon") flow.set("segBasement1", segBasement1, "diskCon")
flow.set("segBasement2", segBasement2, "diskCon") flow.set("segBasement2", segBasement2, "diskCon")
flow.set("segBasement3", segBasement3, "diskCon") flow.set("segBasement3", segBasement3, "diskCon")
flow.set("segBasement4", segBasement4, "diskCon") flow.set("segBasement4", segBasement4, "diskCon")
flow.set("effectSegBasement1", effectSegBasement1, "diskCon")
flow.set("effectSegBasement2", effectSegBasement2, "diskCon")
flow.set("basementFull", basementFull, "diskCon")
flow.set("adaptiveFirstFloor", adaptiveFirstFloor, "diskCon")
flow.set("adaptiveBasement", adaptiveBasement, "diskCon")
flow.set('lightsTinaDesk', lightsTinaDesk, 'diskCon')
flow.set('lightsBasement', lightsBasement, 'diskCon')
flow.set('lightsLivingRoom', lightsLivingRoom, 'diskCon')
flow.set('lightsDiningRoom', lightsDiningRoom, 'diskCon')
flow.set('lightsStairwell', lightsStairwell, 'diskCon')
flow.set('alertFirstFloor', false)
flow.set('alertBasement', false)

View File

@ -1,368 +1,36 @@
// Set constants
const states = global.get('homeassistant.homeAssistant.states') const states = global.get('homeassistant.homeAssistant.states')
const occupied = states["binary_sensor.basement_occupied"].state const occupied = states["binary_sensor.basement_occupied"].state
const quiet = states["input_boolean.studio_quiet"].state const quiet = states["input_boolean.studio_quiet"].state
const stateTinaDesk = states["light.tina_desk_lights"].state const deskState = states["light.tina_desk_lights"].state
const stateLivingRoom = states["light.living_room_lights"].state const livingRoomState = states["light.living_room_lights"].state
const stateDiningRoom = states["light.dining_room_lamp"].state const diningRoomState = states["light.dining_room_lamp"].state
const stateStairwell = states["light.stairwell_led_strip"].state const basementState = states["light.basement_studio_lights"].state
const stateBasement = states["light.basement_studio_lights"].state const where = msg.payload.event.where
const adaptLivingRoom = states["switch.adaptive_lighting_living_room"].state const type = msg.payload.event.type
const adaptDiningRoom = states["switch.adaptive_lighting_dining_room_lamp"].state
const adaptBasement = states["switch.adaptive_lighting_basement_studio"].state
const nightLivingRoom = states["switch.adaptive_lighting_sleep_mode_living_room"].state
const nightDiningRoom = states["switch.adaptive_lighting_sleep_mode_dining_room_lamp"].state
const nightBasement = states["switch.adaptive_lighting_sleep_mode_basement_studio"].state
const currentSceneBasement = states["input_text.basement_studio_selected_scene"].state
const currentSceneLivingRoom = states["input_text.living_room_selected_scene"].state
const currentSceneTinaDesk = states["input_text.tina_desk_selected_scene"].state
const currentSceneDiningRoom = states["input_text.dining_room_lamp_selected_scene"].state
const effectBasement = msg.payload.event.basement
const effectFirstFloor = msg.payload.event.first_floor
const effectColor = msg.payload.event.color
const effectDivide = msg.payload.event.divide
const duration = msg.payload.event.duration const duration = msg.payload.event.duration
const delay = duration * 1000
const adaptiveSwitchFirstFloor = flow.get("adaptiveFirstFloor", "diskCon")
const adaptiveSwitchBasement = flow.get("adaptiveBasement", "diskCon")
const lightsTinaDesk = flow.get('lightsTinaDesk', 'diskCon')
const lightsBasement = flow.get('lightsBasement', 'diskCon')
const lightsLivingRoom = flow.get('lightsLivingRoom', 'diskCon')
const lightsDiningRoom = flow.get('lightsDiningRoom', 'diskCon')
const alertFirstFloor = flow.get('alertFirstFloor')
const alertBasement = flow.get('alertBasement')
// Set flow contexts to be used later in the reset node let firstFloorLights = []
flow.set("currentSceneBasement", currentSceneBasement) let basementLights = []
flow.set("currentSceneLivingRoom", currentSceneLivingRoom)
flow.set("currentSceneTinaDesk", currentSceneTinaDesk)
flow.set('currentSceneDiningRoom', currentSceneDiningRoom)
flow.set("adaptLivingRoom", adaptLivingRoom)
flow.set("adaptBasement", adaptBasement)
flow.set("nightLivingRoom", nightLivingRoom)
flow.set("nightBasement", nightBasement)
flow.set('nightDiningRoom', nightDiningRoom)
flow.set("stateTinaDesk", stateTinaDesk)
flow.set("stateLivingRoom", stateLivingRoom)
flow.set("stateDiningRoom", stateDiningRoom)
flow.set("stateStairwell", stateStairwell)
flow.set("stateBasement", stateBasement)
// Define empty arrays for basement LED strip zones if (deskState === 'on') {
let basement1 = [] firstFloorLights.push('light.tina_desk_strip','light.tina_lamp_top','light.tina_lamp_side')
let basement2 = []
let basementFull = []
// Define empty arrays for living room LED strip zones
let livingRoom1 = []
let livingRoom2 = []
let livingRoomFull = []
// Color names are set by default, however certain effects can override them below
let colorName1 = effectColor
let colorName2 = "white"
// Define empty object for LIFX effect settings
let lifxData = {}
let effectLifx = msg.payload.event.lifx
// Setup the proper zones to use for the effect
if (effectDivide === 'half') {
basement1 = flow.get("halfBasement1", "diskCon")
basement2 = flow.get("halfBasement2", "diskCon")
livingRoom1 = flow.get("halfLivingRoom1", "diskCon")
livingRoom2 = flow.get("halfLivingRoom2", "diskCon")
} else if (effectDivide === 'quarter') {
basement1 = flow.get("effectSegBasement1", "diskCon")
basement2 = flow.get("effectSegBasement2", "diskCon")
livingRoom1 = flow.get("effectSegLivingRoom1", "diskCon")
livingRoom2 = flow.get("effectSegLivingRoom2", "diskCon")
} else if (effectDivide === 'full') {
basementFull = flow.get("basementFull", "diskCon")
livingRoomFull = flow.get("livingRoomFull", "diskCon")
} }
if (effectFirstFloor === true) { if (livingRoomState === 'on') {
flow.set('alertFirstFloor', true) firstFloorLights.push('light.living_room_color_1','light.living_room_color_2','light.living_room_color_3','light.living_room_led_strip')
} }
if (effectBasement === true) { if (diningRoomState === 'on') {
flow.set('alertBasement', true) firstFloorLights.push('light.dining_room_lamp')
} }
// Set/change colors if necessary if (basementState === 'on') {
if (effectColor === 'police') { basementLights.push('light.basement_tall_lamp','light.basement_short_lamp','light.basement_stairwell','light.basement_led_strip_1')
colorName1 = 'red'
colorName2 = 'blue'
} }
// Define parameters for different LIFX effects flow.set("deskState", deskState)
if (effectLifx === 'move') { flow.set("livingRoomState", livingRoomState)
lifxData = { flow.set("diningRoomState", diningRoomState)
"speed": 0.5, flow.set("basementState", basementState)
"direction": "right",
"power_on": false
}
} else if (effectLifx === 'ping') {
effectLifx = 'pulse'
colorName2 = colorName1
lifxData = {
"power_on": false,
"mode": "ping",
"period": 1,
"cycles": duration,
"color_name": "white",
"brightness": 255
}
} else if (effectLifx === 'blink') {
effectLifx = 'pulse'
colorName2 = colorName1
lifxData = {
"power_on": false,
"mode": "blink",
"period": 0.5,
"cycles": duration * 2,
"color_name": "white",
"brightness": 255
}
}
// Define messages // let segLivingRoom = [].concat(segLivingRoom1, segLivingRoom2)
let sendBasementStripFX = {
"payload": {
"domain": "lifx",
"service": "effect_" + effectLifx,
"target": {
"entity_id": ["light.basement_led_strip_1"]
},
"data": lifxData
}
}
let sendBasementStrip1 = {
"payload": {
"domain": "lifx",
"service": "set_state",
"target": {
"entity_id": ["light.basement_led_strip_1"]
},
"data": {
"zones": basement1,
"color_name": colorName1,
"brightness": 255
}
}
}
let sendBasementStrip2 = {
"payload": {
"domain": "lifx",
"service": "set_state",
"target": {
"entity_id": ["light.basement_led_strip_1"]
},
"data": {
"zones": basement2,
"color_name": colorName2,
"brightness": 255,
"power": true
}
}
}
let sendBasementLights = {
"payload": {
"domain": "light",
"service": "turn_on",
"target": {
"entity_id": [
"light.basement_tall_lamp",
"light.basement_short_lamp",
"light.basement_stairwell"
]
},
"data": {
"color_name": colorName1,
"brightness": 255
}
}
}
let sendLivingRoomStripFX = {
"payload": {
"domain": "lifx",
"service": "effect_" + effectLifx,
"target": {
"entity_id": ["light.living_room_led_strip"]
},
"data": lifxData
}
}
let sendLivingRoomStrip1 = {
"payload": {
"domain": "lifx",
"service": "set_state",
"target": {
"entity_id": ["light.living_room_led_strip"]
},
"data": {
"zones": livingRoom1,
"color_name": colorName1,
"brightness": 255
}
}
}
let sendLivingRoomStrip2 = {
"payload": {
"domain": "lifx",
"service": "set_state",
"target": {
"entity_id": ["light.living_room_led_strip"]
},
"data": {
"zones": livingRoom2,
"color_name": colorName2,
"brightness": 255,
"power": true
}
}
}
let sendLivingRoomLights = {
"payload": {
"domain": "light",
"service": "turn_on",
"target": {
"entity_id": [
"light.living_room_color_1",
"light.living_room_color_2",
"light.living_room_color_3",
"light.stairwell_led_strip"
]
},
"data": {
"color_name": colorName1,
"brightness": 255
}
}
}
let sendTinaDeskLights = {
"payload": {
"domain": "light",
"service": "turn_on",
"target": {
"entity_id": ["light.tina_desk_lights"]
},
"data": {
"color_name": colorName1,
"brightness": 255
}
}
}
let sendDiningRoomLamp = {
"payload": {
"domain": "light",
"service": "turn_off",
"target": {
"entity_id": ["light.dining_room_lamp"]
},
"data": {}
}
}
let sendAdaptiveFirstFloor = {
"payload": {
"domain": "switch",
"service": "turn_off",
"target": {
"entity_id": adaptiveSwitchFirstFloor
},
"data": {}
}
}
let sendAdaptiveBasement = {
"payload": {
"domain": "switch",
"service": "turn_off",
"target": {
"entity_id": adaptiveSwitchBasement
},
"data": {}
}
}
let backupLivingRoom = {
"payload": {
"domain": "scene",
"service": "create",
"data": {
"scene_id": "living_room_alert_restore",
"snapshot_entities": lightsLivingRoom
}
}
}
let backupTinaDesk = {
"payload": {
"domain": "scene",
"service": "create",
"data": {
"scene_id": "tina_desk_alert_restore",
"snapshot_entities": lightsTinaDesk
}
}
}
let backupBasement = {
"payload": {
"domain": "scene",
"service": "create",
"data": {
"scene_id": "basement_alert_restore",
"snapshot_entities": lightsBasement
}
}
}
let sendReset = {
"delay": delay
}
let sendDebug = {
"topic": "debug",
"colorName1": colorName1,
"colorName2": colorName2,
"lifxData": lifxData,
"effectLifx": effectLifx,
"basement1": basement1,
"basement2": basement2
}
// Send backup messages
if (stateLivingRoom === 'on' && alertFirstFloor === false) {
node.send([backupLivingRoom,null,null,null,null,null])
}
if (stateTinaDesk === 'on' && alertFirstFloor === false) {
node.send([backupTinaDesk,null,null,null,null,null])
}
if (stateBasement === 'on' && alertBasement === false) {
node.send([backupBasement,null,null,null,null,null])
}
// Send effect messages
if (effectBasement === true) {
node.send([null,null,null,null,[sendAdaptiveBasement,sendBasementLights,sendBasementStripFX,sendBasementStrip1,sendBasementStrip2,sendDebug],null])
}
if (effectFirstFloor === true) {
node.send([null,[sendAdaptiveFirstFloor,sendLivingRoomLights,sendLivingRoomStripFX,sendLivingRoomStrip1,sendLivingRoomStrip2],sendTinaDeskLights,sendDiningRoomLamp,null,null])
}
// Send the reset message to start the timer
node.send([null,null,null,null,null,sendReset])
node.status({fill:'green',shape:'dot',text:'Alert Sent'})

View File

@ -1,326 +0,0 @@
// Set constants
const states = global.get('homeassistant.homeAssistant.states')
const currentSceneBasement = flow.get('currentSceneBasement')
const currentSceneLivingRoom = flow.get('currentSceneLivingRoom')
const currentSceneTinaDesk = flow.get('currentSceneTinaDesk')
const currentSceneDiningRoom = flow.get('currentSceneDiningRoom')
const adaptLivingRoom = flow.get('adaptLivingRoom')
const adaptBasement = flow.get('adaptBasement')
const nightLivingRoom = flow.get('nightLivingRoom')
const nightBasement = flow.get('nightBasement')
const nightDiningRoom = flow.get('nightDiningRoom')
const stateTinaDesk = flow.get('stateTinaDesk')
const stateLivingRoom = flow.get('stateLivingRoom')
const stateDiningRoom = flow.get('stateDiningRoom')
const stateBasement = flow.get('stateBasement')
const stateStairwell = flow.get('stateStairwell')
const scenesLivingRoom = states["input_select.living_room_scenes"].attributes.options
const scenesBasement = states["input_select.basement_studio_scenes"].attributes.options
const scenesTinaDesk = states["input_select.tina_desk_scenes"].attributes.options
const scenesDiningRoom = states["input_select.dining_room_lamp_scenes"].attributes.options
const definedLivingRoom = scenesLivingRoom.includes(currentSceneLivingRoom)
const definedBasement = scenesBasement.includes(currentSceneBasement)
const definedTinaDesk = scenesTinaDesk.includes(currentSceneTinaDesk)
const definedDiningRoom = scenesDiningRoom.includes(currentSceneDiningRoom)
// Define variables
let setSceneLivingRoom = []
let setSceneTinaDesk = []
let setSceneBasement = []
let setSceneDiningRoom = []
let setServiceLivingRoom = []
let setServiceTinaDesk = []
let setServiceDiningRoom = []
let setServiceBasement = []
let restoreLivingRoom = {}
let restoreTinaDesk = {}
let restoreBasement = {}
// Decide what to restore for each room
if (stateLivingRoom === 'on') {
setServiceLivingRoom = 'turn_on'
if (definedLivingRoom === true) {
restoreLivingRoom = 'defined'
setSceneLivingRoom = currentSceneLivingRoom
} else if (nightLivingRoom === 'on') {
restoreLivingRoom = 'night'
setSceneLivingRoom = 'Adaptive'
} else if (adaptLivingRoom === 'on') {
restoreLivingRoom = 'adaptive'
setSceneLivingRoom = 'Adaptive'
} else {
restoreLivingRoom = 'backup'
setSceneLivingRoom = 'living_room_alert_restore'
}
} else {
restoreLivingRoom = 'off'
setServiceLivingRoom = 'turn_off'
setSceneLivingRoom = 'Adaptive'
}
if (stateTinaDesk === 'on') {
setServiceTinaDesk = 'turn_on'
if (definedTinaDesk === true) {
restoreTinaDesk = 'defined'
setSceneTinaDesk = currentSceneTinaDesk
} else {
restoreTinaDesk = 'adaptive'
setSceneTinaDesk = 'Reset'
}
} else {
restoreTinaDesk = 'off'
setServiceTinaDesk = 'turn_off'
}
if (stateDiningRoom === 'on') {
setServiceDiningRoom = 'turn_on'
if (nightDiningRoom === 'on') {
setSceneDiningRoom = 'Nightlight'
} else {
setSceneDiningRoom = 'Adaptive'
}
} else {
setServiceDiningRoom = 'turn_off'
}
if (stateBasement === 'on') {
setServiceBasement = 'turn_on'
if (definedBasement === true) {
restoreBasement = 'defined'
setSceneBasement = currentSceneBasement
} else if (nightBasement === 'on') {
restoreBasement = 'night'
setSceneBasement = 'Adaptive'
} else if (adaptBasement === 'on') {
restoreBasement = 'adaptive'
setSceneBasement = 'Adaptive'
} else {
restoreBasement = 'backup'
setSceneBasement = 'basement_alert_restore'
}
} else {
restoreBasement = 'off'
setServiceBasement = 'turn_off'
setSceneBasement = 'Adaptive'
}
// Define messages
let sendSceneLivingRoom = {
"payload": {
"domain": "input_select",
"service": "select_option",
"target": {
"entity_id": ["input_select.living_room_scenes"]
},
"data": {
"option": setSceneLivingRoom
}
}
}
let sendSceneTinaDesk = {
"payload": {
"domain": "input_select",
"service": "select_option",
"target": {
"entity_id": ["input_select.tina_desk_scenes"]
},
"data": {
"option": setSceneTinaDesk
}
}
}
let sendSceneBasement = {
"payload": {
"domain": "input_select",
"service": "select_option",
"target": {
"entity_id": ["input_select.basement_studio_scenes"]
},
"data": {
"option": setSceneBasement
}
}
}
let sendSceneDiningRoomLamp = {
"payload": {
"domain": "input_select",
"service": "select_option",
"target": {
"entity_id": ["input_select.dining_room_lamp_scenes"]
},
"data": {
"option": setSceneDiningRoom
}
}
}
let sendNightLivingRoom = {
"payload": {
"domain": "switch",
"service": "turn_on",
"target": {
"entity_id": ["switch.adaptive_lighting_sleep_mode_living_room"]
},
"data": {}
}
}
let sendNightTinaDesk = {
"payload": {
"domain": "switch",
"service": "turn_on",
"target": {
"entity_id": ["switch.adaptive_lighting_sleep_mode_tina_desk"]
},
"data": {}
}
}
let sendNightBasement = {
"payload": {
"domain": "switch",
"service": "turn_on",
"target": {
"entity_id": ["switch.adaptive_lighting_sleep_mode_basement_studio"]
},
"data": {}
}
}
let sendStateLivingRoom = {
"payload": {
"domain": "light",
"service": setServiceLivingRoom,
"target": {
"entity_id": ["light.living_room_lights"]
},
"data": {}
}
}
let sendStateTinaDesk = {
"payload": {
"domain": "light",
"service": setServiceTinaDesk,
"target": {
"entity_id": ["light.tina_desk_lights"]
},
"data": {}
}
}
let sendStateDiningRoom = {
"payload": {
"domain": "light",
"service": setServiceDiningRoom,
"target": {
"entity_id": ["light.dining_room_lamp"]
},
"data": {}
}
}
let sendStateBasement = {
"payload": {
"domain": "light",
"service": setServiceBasement,
"target": {
"entity_id": ["light.basement_studio_lights"]
},
"data": {}
}
}
let sendRestoreLivingRoom = {
"payload": {
"domain": "scene",
"service": "turn_on",
"target": {
"entity_id": setSceneLivingRoom
},
"data": {}
}
}
let sendRestoreTinaDesk = {
"payload": {
"domain": "scene",
"service": "turn_on",
"target": {
"entity_id": setSceneTinaDesk
},
"data": {}
}
}
let sendRestoreBasement = {
"payload": {
"domain": "scene",
"service": "turn_on",
"target": {
"entity_id": setSceneBasement
},
"data": {}
}
}
let sendStairwellScript = {
"payload": {
"domain": "script",
"service": "stairwell_led_strip",
"data": {}
}
}
let sendStairwellOff = {
"payload": {
"domain": "light",
"service": "turn_off",
"target": {
"entity_id": ["light.stairwell_led_strip"]
},
"data": {}
}
}
// Send messages
if (restoreLivingRoom === 'backup') {
node.send([sendRestoreLivingRoom,null,null,null])
} else if (restoreLivingRoom === 'off') {
node.send([sendStateLivingRoom,null,null,null])
} else {
node.send([sendSceneLivingRoom,null,null,null])
}
if (restoreTinaDesk === 'backup') {
node.send([null,sendRestoreTinaDesk,null,null])
} else if (restoreTinaDesk === 'off') {
node.send([null,sendStateTinaDesk,null,null])
} else {
node.send([null,sendSceneTinaDesk,null,null])
}
node.send([null,null,[sendStateDiningRoom,sendSceneDiningRoomLamp],null])
if (restoreBasement === 'backup') {
node.send([null,null,null,sendRestoreBasement])
} else if (restoreBasement === 'off') {
node.send([null,null,null,sendStateBasement])
} else {
node.send([null,null,null,sendSceneBasement])
}
if (stateStairwell === 'on') {
node.send([sendStairwellScript,null,null,null])
} else {
node.send([sendStairwellOff,null,null,null])
}
flow.set('alertFirstFloor', false)
flow.set('alertBasement', false)
node.status({fill:'green',shape:'dot',text:'Scenes Reset'})

View File

@ -9,17 +9,22 @@ const newDuration = duration * 60
if (sleeping === 'off') { if (sleeping === 'off') {
if (payload === 'on') { if (payload === 'on') {
if (lux <= threshold || lights === 'on') { if (lux <= threshold && lights === 'off') {
node.status({fill:'green',shape:'dot',text:'Lights On'}) node.status({fill:'green',shape:'dot',text:'Turning lights on'})
node.send([msg,null]) node.send([msg,msg,null])
} else { } else {
node.status({fill:'red',shape:'ring',text:'Too bright'}) if (lights === 'on') {
node.status({fill:'red',shape:'ring',text:'Lights already on'})
node.send([null,msg,null])
} else {
node.status({fill:'red',shape:'ring',text:'Too bright'})
}
} }
} else if (payload === 'off') { } else if (payload === 'off') {
if (lights === 'on') { if (lights === 'on') {
msg.duration = newDuration msg.duration = newDuration
node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'}) node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'})
node.send([null,msg]) node.send([null,null,msg])
} else { } else {
node.status({fill:"red",shape:"ring",text:"Lights already off"}) node.status({fill:"red",shape:"ring",text:"Lights already off"})
} }

View File

@ -9,17 +9,22 @@ const newDuration = duration * 60
if (sleeping === 'off') { if (sleeping === 'off') {
if (payload === 'on') { if (payload === 'on') {
if (lux <= threshold || lights === 'on') { if (lux <= threshold && lights === 'off') {
node.status({fill:'green',shape:'dot',text:'Lights On'}) node.status({fill:'green',shape:'dot',text:'Turning lights on'})
node.send([msg,null]) node.send([msg,msg,null])
} else { } else {
node.status({fill:'red',shape:'ring',text:'Too bright'}) if (lights === 'on') {
node.status({fill:'red',shape:'ring',text:'Lights already on'})
node.send([null,msg,null])
} else {
node.status({fill:'red',shape:'ring',text:'Too bright'})
}
} }
} else if (payload === 'off') { } else if (payload === 'off') {
if (lights === 'on') { if (lights === 'on') {
msg.duration = newDuration msg.duration = newDuration
node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'}) node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'})
node.send([null,msg]) node.send([null,null,msg])
} else { } else {
node.status({fill:"red",shape:"ring",text:"Lights already off"}) node.status({fill:"red",shape:"ring",text:"Lights already off"})
} }

View File

@ -12,17 +12,22 @@ const newDuration = duration * 60
if (peopleSleeping === false && nightMode === 'off') { if (peopleSleeping === false && nightMode === 'off') {
if (payload === 'on') { if (payload === 'on') {
if (lux <= threshold || lights === 'on') { if (lux <= threshold && lights === 'off') {
node.status({fill:'green',shape:'dot',text:'Lights On'}) node.status({fill:'green',shape:'dot',text:'Turning lights on'})
node.send([msg,null]) node.send([msg,msg,null])
} else { } else {
node.status({fill:'red',shape:'ring',text:'Too bright'}) if (lights === 'on') {
node.status({fill:'red',shape:'ring',text:'Lights already on'})
node.send([null,msg,null])
} else {
node.status({fill:'red',shape:'ring',text:'Too bright'})
}
} }
} else if (payload === 'off') { } else if (payload === 'off') {
if (lights === 'on') { if (lights === 'on') {
msg.duration = newDuration msg.duration = newDuration
node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'}) node.status({fill:"green",shape:"dot",text:parseInt(duration) + ' minutes'})
node.send([null,msg]) node.send([null,null,msg])
} else { } else {
node.status({fill:"red",shape:"ring",text:"Lights already off"}) node.status({fill:"red",shape:"ring",text:"Lights already off"})
} }

View File

@ -127,8 +127,7 @@ node.log("Time-based Automations: Decision Logic Complete")
// ---------- Service Calls ---------- // ---------- Service Calls ----------
let sendLights = { let sendLights = {
"payload": { "payload": {
"domain": "light", "action": "light.turn_off",
"service": "turn_off",
"target": { "target": {
"entity_id": lightsOff "entity_id": lightsOff
}, },
@ -138,8 +137,7 @@ let sendLights = {
let sendSleepOff = { let sendSleepOff = {
"payload": { "payload": {
"domain": "switch", "action": "switch.turn_off",
"service": "turn_off",
"target": { "target": {
"entity_id": adaptiveSleep "entity_id": adaptiveSleep
}, },
@ -149,8 +147,7 @@ let sendSleepOff = {
let sendBooleanOff = { let sendBooleanOff = {
"payload": { "payload": {
"domain": "input_boolean", "action": "input_boolean.turn_off",
"service": "turn_off",
"target": { "target": {
"entity_id": booleanOff "entity_id": booleanOff
}, },
@ -160,8 +157,7 @@ let sendBooleanOff = {
let sendAdaptive = { let sendAdaptive = {
"payload": { "payload": {
"domain": "switch", "action": "switch.turn_" + setAdaptive,
"service": "turn_" + setAdaptive,
"target": { "target": {
"entity_id": switchAdaptive "entity_id": switchAdaptive
}, },
@ -171,8 +167,7 @@ let sendAdaptive = {
let sendSceneResetMain = { let sendSceneResetMain = {
"payload": { "payload": {
"domain": "input_text", "action": "input_text.set_value",
"service": "set_value",
"target": { "target": {
"entity_id": selScenesMain "entity_id": selScenesMain
}, },
@ -184,8 +179,7 @@ let sendSceneResetMain = {
let sendSceneResetDesk = { let sendSceneResetDesk = {
"payload": { "payload": {
"domain": "input_text", "action": "input_text.set_value",
"service": "set_value",
"target": { "target": {
"entity_id": selScenesTinaDesk "entity_id": selScenesTinaDesk
}, },
@ -197,8 +191,7 @@ let sendSceneResetDesk = {
let sendHoliday = { let sendHoliday = {
"payload": { "payload": {
"domain": "switch", "action": "switch.turn_" + setHoliday,
"service": "turn_" + setHoliday,
"target": { "target": {
"entity_id": switchHoliday "entity_id": switchHoliday
}, },
@ -208,8 +201,7 @@ let sendHoliday = {
let sendTimer = { let sendTimer = {
"payload": { "payload": {
"domain": "timer", "action": "timer.start",
"service": "start",
"target": { "target": {
"entity_id": timerEntity "entity_id": timerEntity
}, },
@ -221,8 +213,7 @@ let sendTimer = {
let sendTimerCancel = { let sendTimerCancel = {
"payload": { "payload": {
"domain": "timer", "action": "timer.cancel",
"service": "cancel",
"target": { "target": {
"entity_id": timerEntity "entity_id": timerEntity
}, },
@ -232,8 +223,7 @@ let sendTimerCancel = {
let sendNotifyPhone = { let sendNotifyPhone = {
"payload": { "payload": {
"domain": "script", "action": "script.text_notify",
"service": "text_notify",
"data": { "data": {
"who": "all", "who": "all",
"title": notifyTitle, "title": notifyTitle,
@ -246,8 +236,7 @@ let sendNotifyPhone = {
let sendNotifyTV = { let sendNotifyTV = {
"payload": { "payload": {
"domain": "script", "action": "script.tv_notify",
"service": "tv_notify",
"data": { "data": {
"who": "all", "who": "all",
"title": notifyTitle, "title": notifyTitle,
@ -263,8 +252,7 @@ let sendNotifyTV = {
let sendFirstFloorScene = { let sendFirstFloorScene = {
"payload": { "payload": {
"domain": "script", "action": "script.evening_on_first_floor",
"service": "evening_on_first_floor",
"data": { "data": {
"sunset_lights": 1 "sunset_lights": 1
} }
@ -273,8 +261,7 @@ let sendFirstFloorScene = {
let sendSecondFloorScene = { let sendSecondFloorScene = {
"payload": { "payload": {
"domain": "script", "action": "script.evening_on_second_floor",
"service": "evening_on_second_floor",
"data": { "data": {
"sunset_lights": 1 "sunset_lights": 1
} }
@ -283,8 +270,7 @@ let sendSecondFloorScene = {
let sendDeskScene = { let sendDeskScene = {
"payload": { "payload": {
"domain": "input_select", "action": "input_select.select_option",
"service": "select_option",
"target": { "target": {
"entity_id": ["input_select.tina_desk_scenes"] "entity_id": ["input_select.tina_desk_scenes"]
}, },

View File

@ -0,0 +1,26 @@
let tomorrow = msg.tomorrow
let today = msg.today
let number = {}
let work_tomorrow = {}
if (tomorrow > 0) {
work_tomorrow = "true"
if (today == 0) {
number = 0
} else {
number = 1
}
} else {
work_tomorrow = "false"
number = 0
}
msg.work_tomorrow = work_tomorrow
node.status({fill:"green",shape:"dot",text:"Number " + number})
if (number == 0) {
node.send([msg,null])
} else {
node.send([null,msg])
}

74
weather/alerts_filter.js Normal file
View File

@ -0,0 +1,74 @@
const severeWarningEvents = ["Severe Thunderstorm Warning","Destructive Severe Thunderstorm Warning","Considerable Destructive Severe Thunderstorm Warning"]
const tornadoWarningEvents = ["Tornado Warning","Radar Indicated Tornado Warning","Confirmed Tornado Warning","Tornado Emergency"]
let alerts = msg.payload
// Filter for Severe Thunderstorm Warnings
let ts = alerts.filter(function(alert) {
if (alert.raw.properties &&
severeWarningEvents.includes(alert.raw.properties.event)) {
return true
}
})
// Filter for Severe Thunderstorm Warnings with tornado detection
// that have a tornado possible parameter
let tstp = alerts.filter(function(alert) {
if (alert.raw.properties &&
severeWarningEvents.includes(alert.raw.properties.event) &&
alert.raw.properties.parameters &&
alert.raw.properties.parameters.tornadoDetection &&
alert.raw.properties.parameters.tornadoDetection.length > 0) {
let tornadoPossible = alert.raw.properties.parameters.tornadoDetection[0]
return tornadoPossible === "POSSIBLE"
}
})
// Filter for considerable destructive severe thunderstorm warnings
let cdst = alerts.filter(function(alert) {
if (alert.raw.properties &&
alert.raw.properties.event === "Considerable Destructive Severe Thunderstorm Warning") {
return true
}
})
// Filter for Tornado Warnings
let tornado = alerts.filter(function(alert) {
if (alert.raw.properties &&
tornadoWarningEvents.includes(alert.raw.properties.event)) {
return true
}
})
let confirmed_tornado = alerts.filter(function(alert) {
if (alert.raw.properties &&
alert.raw.properties.event === "Confirmed Tornado Warning") {
return true
}
})
// If there are any alerts, return them
let tstormMsg = {
"payload": {
"alerts": ts,
"count": ts.length,
"tornado_possible": tstp.length,
"considerable_destructive": cdst.length
}
}
let tornadoWarnMsg = {
"payload": {
"alerts": tornado,
"count": tornado.length,
"confirmed": confirmed_tornado.length
}
}
node.send([tstormMsg,tornadoWarnMsg])
node.status({fill:'green',shape:'dot',text:'Alerts Updated'})

148
weather/local_alerts.js Normal file
View File

@ -0,0 +1,148 @@
const severeWarningEvents = ["Severe Thunderstorm Warning","Destructive Severe Thunderstorm Warning","Considerable Destructive Severe Thunderstorm Warning"]
const tornadoWarningEvents = ["Tornado Warning","Radar Indicated Tornado Warning","Confirmed Tornado Warning","Tornado Emergency"]
const tornadoWatchEvents = ["Tornado Watch"]
const severeThunderstormWatchEvents = ["Severe Thunderstorm Watch"]
const area = msg.area
const mqttTopic = "weather/alerts/" + area
const tstormTopic = mqttTopic + "/severe_thunderstorm_warning"
const tornadoWarnTopic = mqttTopic + "/tornado_warning"
const tornadoWatchTopic = mqttTopic + "/tornado_watch"
const severeThunderstormWatchTopic = mqttTopic + "/severe_thunderstorm_watch"
let alerts = msg.payload.features
let tornado_possible = false
let considerable_destructive = false
let confirmed = false
// Filter for Severe Thunderstorm Warnings
let ts = alerts.filter(function(alert) {
if (alert.properties &&
severeWarningEvents.includes(alert.properties.event)) {
return true
}
})
// Filter for Severe Thunderstorm Warnings with tornado detection
// that have a tornado possible parameter
let tstp = alerts.filter(function(alert) {
if (alert.properties &&
severeWarningEvents.includes(alert.properties.event) &&
alert.properties.parameters &&
alert.properties.parameters.tornadoDetection &&
alert.properties.parameters.tornadoDetection.length > 0) {
let tornadoPossible = alert.properties.parameters.tornadoDetection[0]
return tornadoPossible === "POSSIBLE"
}
})
if (tstp.length > 0) {
tornado_possible = true
}
// Filter for considerable destructive severe thunderstorm warnings
let cdst = alerts.filter(function(alert) {
if (alert.properties &&
alert.properties.event === "Considerable Destructive Severe Thunderstorm Warning") {
return true
}
})
if (cdst.length > 0) {
considerable_destructive = true
}
// Filter for Tornado Warnings
let tornado = alerts.filter(function(alert) {
if (alert.properties &&
tornadoWarningEvents.includes(alert.properties.event)) {
return true
}
})
let confirmed_tornado = alerts.filter(function(alert) {
if (alert.properties &&
alert.properties.event === "Confirmed Tornado Warning") {
return true
}
})
if (confirmed_tornado.length > 0) {
confirmed = true
}
// Filter for Tornado Watches
let tornado_watch = alerts.filter(function(alert) {
if (alert.properties &&
tornadoWatchEvents.includes(alert.properties.event)) {
return true
}
})
// Filter for Severe Thunderstorm Watches
let severe_thunderstorm_watch = alerts.filter(function(alert) {
if (alert.properties &&
severeThunderstormWatchEvents.includes(alert.properties.event)) {
return true
}
})
// If there are any alerts, return them
let allAlerts = {
"payload": msg.payload.features
}
let tstormMsg = {
"payload": {
"alerts": ts,
"count": ts.length,
"tornado_possible": tornado_possible,
"considerable_destructive": considerable_destructive
},
"topic": tstormTopic
}
let tornadoWarnMsg = {
"payload": {
"alerts": tornado,
"count": tornado.length,
"confirmed": confirmed
},
"topic": tornadoWarnTopic
}
let tornadoWatchMsg = {
"payload": {
"alerts": tornado_watch,
"count": tornado_watch.length
},
"topic": tornadoWatchTopic
}
let severeThunderstormWatchMsg = {
"payload": {
"alerts": severe_thunderstorm_watch,
"count": severe_thunderstorm_watch.length
},
"topic": severeThunderstormWatchTopic
}
// Create status message for node
let statusMsg = {
"status": {
"fill": "green",
"shape": "dot",
"text": alerts.length + " alerts processed at " + new Date().toLocaleString()
}
}
// Send messages to output nodes
node.send([allAlerts,tstormMsg,tornadoWarnMsg,tornadoWatchMsg,severeThunderstormWatchMsg,statusMsg])