Hi everyone,
As a n00b Hubitat user I have been wrestling a bit with calling my main HTTPS Node Red installation from a Rule Engine trigger. Now that I have it working someone else might benefit from the experience. I use Hubitat Elevation as a convenient bridge to collate events from (plentiful) ZigBee devices into Node Red.
Prerequisites
- You need to have the latest Rule Machine installed, so update your Hubitat Elevation to latest version before you start this process.
Step 1: Install a "notification device" driver that can do an HTTPS submit
The standard Rule Engine HTTP GET does not have a flag to ignore SSL warnings, so I couldn't call my local instance of Node Red - it has a self signed certificate which caused enough SSL warnings to abort the request.
The driver code is below, all credit goes to Brian Johnson since I only added ignoreSSLIssues: true.
/**
* File: HTTP-Notifications.groovy
* Platform: Hubitat
* Modification History:
* Date Who What
* v1.0.0 2020-08-16 Brian Johnson Initial version
*
* Copyright (c) 2020 Brian Johnson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
def version() {"v1.0.0"}
metadata
{
definition (
name: "HTTP Notifications",
namespace: "john3300",
author: "Brian Johnson",
description: "Send notification messages to an HTTP URL via GET",
importUrl: "https://raw.githubusercontent.com/john3300/Hubitat-HTTPNotifications/HTTP-Notifications.groovy"
)
{
capability "Actuator"
capability "Notification"
capability "PushableButton"
}
preferences
{
input name: "httpUrl", type: "text", title: "Notification URL:", required: true
input name: "queryString", type: "text", title: "Query String:", description: "Use <MSG> as placeholder for message", required: false
}
}
def push(buttonNumber)
{
deviceNotification(message)
}
def deviceNotification(message)
{
// Sending message [device=LOUNGE_BUTTON&event=PRESS&pushed=5] to [https://192.168.1.110:1880/notify]
log.debug "Sending message [${message}] to [${httpUrl}]"
/**
* params options
*
* uri - The uri to send the request to
* queryString - The raw, already-escaped query string.
* query - Add these parameters to the existing query string. If any of the parameters already exist in the query, these values will not replace them. Multiple values for the same query parameter may be added by putting them in a list.
* headers - Request headers
* path - The path component of this request. The value may be absolute or relative to the current path.
* contentType - The content-type used for any data in the request body, as well as the Accept content-type that will be used for parsing the response.
* requestContentType - Assign a different content-type for the request than is expected for the response.
* timeout (since 2.0.9) - timeout in seconds for the request, max timeout is 300
* textParser (since 2.1.1) - possible values: true, false. If set to true, the response will be parsed as plain text, if false the system will attempt to determine the content type and parse the response into an object. Defaults to false.
* ignoreSSLIssues (since 2.1.8) - possible values: true, false. Ignores certificate issues for SSL connections. Cert does not have to be from a trusted authority and the hostname does not need to be verified. This is primarily for dev situations that make use of localhost, build, and test servers. Defaults to false.
*/
def params =
[
uri: httpUrl,
contentType: "text/plain",
ignoreSSLIssues: true
]
if (queryString)
{
queryString = queryString.replaceAll("<MSG>", URLEncoder.encode(message, "UTF-8"))
log.debug "Query String is [${queryString}]"
params.put("queryString", queryString)
}
else
{
log.debug "Query String is [${message}]"
params.put("queryString", message)
}
try
{
httpGet(params)
{
response -> if (response.status >= 300)
{
log.debug "Received HTTP error ${response.status}!"
}
else
{
log.debug "Message delivered, response: ${response.data}"
}
}
}
catch (Exception e)
{
log.error "Error calling httpPost ${e}"
}
}
Step 2: Install the Notifications app (may work without this step?)
- Click on [Apps] and [Add Built-In App], scroll down to Notifications.
Step 3: Add an instance of HTTP notifier to talk to your Node Red webhooks (or your own webhooks)
You need to create an instance of a Virtual Device to do this, configured to point to your special URL.
-
Click on [Devices] and [Add Virtual Device]
-
In âDevice Nameâ and âDevice Labelâ put something like âNode Red HTTPSâ.
-
In âTypeâ scroll down to the bottom to the âUserâ section and choose the driver you just added, called âHTTP Notificationsâ.
-
Click [Save Device] and the screen will refresh to show an additional field âNotification URLâ
-
In âNotification URLâ you just want to put the base of the URL, without any parameters. i.e. in the URL this is the part before the â?â character. For example, in my case, it is âhttps://192.168.0.202:1578/node-webhookâ. A full URL might look like âhttps://192.168.0.202:1578/node-webhook?sensor=GARAGE_DOOR&contact=openâ
-
Leave Query String blank, and Click [Save Preferences]
Step 4: Install the zigbee device
- Plenty of tutorials on how to do this so I am not repeating this here.
Step 5: Add a Rule to trigger when something changes
-
Click on [Apps] and [Add Built-In App], scroll down to âRule Machineâ.
-
Click [Create New Rule]
-
Put a title in, something like âGARAGE_DOOR changedâ
-
Click [Select Trigger Events]
-
In âSelect capability for new Trigger Eventâ, choose a kind of event to match the device you are adding. In my case this is âContactâ because itâs a contact sensor. Press [TAB] to refresh the screen once you have selected one (if it doesnât automatically refresh the panel).
-
Where it says [Contact Sensors * Click to Set] click it and choose the sensor you want to trigger events from and click [Update]. It will show every sensor you have with that capability. In my case, I ticked my previously defined âContact Sensor - GARAGE_DOORâ.
-
Under âContact reportsâ set it to âChangedâ since we want to pass ANY change to Node Red. Click [Done with this Trigger Event] and then [Done with Trigger Events].
(for more complex sensors that can have many different events I would add all of them here as triggers so no matter what happens to the sensor you can send them all to Node Red if you are using the Hubitat Elevation as a simple bridge).
Step 6: Add a local variable to use as a URL parameter
You need to do this, because strangely you canât use device attributes as %parameter% in the URL, only variables.
-
Click on [Create Local Variables] and [New Variable]
-
Type in a name for the variable and hit [TAB], in this case I used âcontactâ and selected String because it contains a word. For things like temperature sensors, just use Number. Initial value is optional, since it will be overwritten the moment an event comes in.
-
Add a local variable for each attribute you need to pass to Node Red from the sensor, then click [Done with Local Variables].
Step 7: Create an action to copy physical device attributes into Local Variables.
-
Click [Select Actions to Run], [Select Actions to Add], [Set Mode, Variables or File, Run Custom Action] and [Set Variable].
-
In [Select Variable to Set] choose the variable you have defined and in [Select string operation] which appears, choose âDevice attributeâ. Select the device you used in your previous trigger (in my case it is âContact Sensor - GARAGE_DOORâ) and click [Update] and choose the attribute you want to copy into the Local Variable (in my case it is âcontactâ but I might also pass the battery reading as well at some point soon).
-
Donât put any delay in there â in an IOT system your worst enemy is delay!
-
Click [Done with this action]
Step 8: pass notifications from the device to Node Red
-
Click [Select Actions to Run] or [Select Actions to Add] depending which screen you are on and [Send, Speak or Log a Message, Send HTTP Request] and then [Send or Speak a Message]. If you donât have âSend or Speak a Messageâ available, you probably have to update your Hubitat Elevation version to get the latest Rule Machine codebase.
-
In [Message to Send] put the parameters for your URL here (i.e. everything after the â?â) e.g. in my case it is âsensor=GARAGE_DOOR&contact=%contact%â. Notice that the parameters I am sending through all come from Local Variables whenever you use the % symbol â we defined the âcontactâ variable earlier.
-
Under [Select notification devices] choose your virtual device âNode Red HTTPSâ and [Update]. No delay!. Click [Done with this action] and [Done with Actions].