d_sellers1

Ping response handler

Oct 11th, 2021
280
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Description: This function is for use with Home Assistant and Node-Red. It will
  2. // turn on a specified light and set it to a specified color in the event of an
  3. // Internet outage. Upon re-connecting, the function will return the light to its
  4. // original state. Note that in order to operate properly, the specified light
  5. // must be locally controlled and not cloud controlled.
  6.  
  7. // Input for this function is a Ping node. Tested with a target identified, automatic
  8. // protocol, timed mode, and an interval of 30 seconds.
  9.  
  10. // For testing purposes, the target IP was set as a WiFi light bulb. To simulate an
  11. // outage, power was turned off to the light. When power was turned back on, the
  12. // re-connect portion would excute.
  13.  
  14. // This function node requires three outputs. These outputs should allow for
  15. // expanded functionality outside the scope of this function node.
  16. // -the first output is for the failure path; payload = number of ping failures
  17. // -the second output is for the operational path; payload = ping response time
  18. // -the third output connects to an empty call service node for the notification.
  19. // payload sends the necessary variables in the event of an outage and re-connection.
  20.  
  21. // Bug: function will sometimes throw a ReferenceError: local is not defined
  22. // Reason: not sure. seems random. mostly noticed when forcing scripts to restart.
  23. // Fix: unknown. tried a couple different ways to define local and they all did
  24. // the same thing.
  25.  
  26. // Bug: During an outage, if the light's state or attributes are changed, the
  27. // function will still return it back to how it was before the outage was reported.
  28. // Reason: The light's state and attributes are stored prior to an outage. It does
  29. // not check if the state has changed during the outage.
  30. // Fix: None yet. Maybe checking during the outage to see if the current
  31. // state/attributes matches the outage state/attributes?
  32.  
  33. // Note: The function does have a variable for the time of failure but it is not
  34. // used for anything yet. Maybe it will get added to the HA log in the future.
  35.  
  36. //20211009 - Added node.status message
  37.  
  38. // This is the entity that will be used for notification of an outage and
  39. // setting previous state.
  40. var entity = "light.hallway";
  41. //This is the color the light will change to during an outage.
  42. var rgb_out = [255,0,0];
  43. // This sets how many consecutive ping failures can occur before triggering the
  44. // outage notification.
  45. var max_allowed_ping_failures = 2;
  46.  
  47. // This function stores the current state of the entity (on/off). If the entity is
  48. // on, it will also stores the entity's attributes. These values will be used when
  49. // returning the entity to its previous state once the internet has re-connected.
  50. function set_entity_previous() {
  51.     local.previous_state = ha.state;
  52.     if (local.previous_state === "on") //Store entity's attributes if state is on
  53.     {
  54.         local.previous_attributes = ha.attributes;
  55.     } else {
  56.         local.previous_attributes = null
  57.     }
  58. }
  59.  
  60. // Initialize variables
  61. const ha = global.get('homeassistant').homeAssistant.states[entity]
  62. const messages = new Array(node.outputCount) // Create an array same length as there are outputs
  63. const msg0 = {payload:"", topic:"MSG0"};
  64. const msg1 = {payload:"", topic:"MSG1"};
  65. const msg2 = {payload:"", data:"", topic:"MSG2"};
  66.  
  67. // Establish variables if they do not exist and set default value
  68. if (typeof local !== undefined) { local = global.get('data') || {}; }
  69. if (local.ping_failure_count===undefined) { local.ping_failure_count = 0; }
  70. if (local.ping_failure_time===undefined) { local.ping_failure_time = 0; }
  71.  
  72. // Establish standard payload to be passed to service call node
  73. msg2.payload = {domain: "light", service: "turn_on",
  74.     data: {
  75.         entity_id: entity, }
  76.     };
  77.  
  78. // The Ping node will return false if it does not receive a response.
  79. // Otherwise, it will return a time in ms.
  80. if (msg.payload === false) // Ping response failed
  81. {
  82.     node.status({fill:"red",shape:"ring",text:"disconnected"});
  83.     local.ping_failure_count++;
  84.    
  85.     // Has max_allowed_ping_failures occured? Indicate outage.
  86.     if (local.ping_failure_count === max_allowed_ping_failures)
  87.     {
  88.         if (local.previous_state === "on" || local.previous_state === "off") { set_entity_previous(); }
  89.         local.ping_failure_time = Date.now(); //Creates timestamp variable in seconds; not used yet
  90.         msg2.payload.data.rgb_color = rgb_out;
  91.         messages[2] = msg2; // Send service call payload to output
  92.     }
  93.    
  94.     msg0.payload = local.ping_failure_count;
  95.     global.set('data',local);
  96.     messages[0] = msg0; // Send ping failure count to output
  97.  
  98. } else { // Ping response good
  99.     node.status({fill:"green",shape:"dot",text:"connected"});
  100.     // Has the internet re-connected following an outage?
  101.     if (local.ping_failure_count >= max_allowed_ping_failures)
  102.     {
  103.         //Return light to its previous state
  104.         if (local.previous_state === "on")
  105.         {
  106.             msg2.payload.data.brightness = local.previous_attributes.brightness;
  107.             // Was light in color mode or RGB mode since both cannot be passed in the same payload?
  108.             if (local.previous_attributes.rgb_color.toString() === '255,255,255') {
  109.                 msg2.payload.data.color_temp = local.previous_attributes.color_temp;
  110.             } else {
  111.                 msg2.payload.data.rgb_color = local.previous_attributes.rgb_color;
  112.             }    
  113.         } else { // Light's previous state was off
  114.             msg2.payload.service = "turn_off";
  115.         }
  116.         messages[2] = msg2;  // Send service call payload to output
  117.     }
  118.    
  119.     local.ping_failure_count = 0; // Reset/maintain ping failure count to zero
  120.     set_entity_previous(); // Store entity's current state
  121.     msg1.payload = msg.payload;
  122.     global.set('data',local);
  123.     messages[1] = msg1;  // Send response time to output
  124. }
  125. return messages;
Advertisement
Add Comment
Please, Sign In to add comment