node-red-contrib-hubitat
Version:
Node Red module for Hubitat API
188 lines (180 loc) • 7.36 kB
HTML
<script src="hubitat/js/common.js"></script>
<script type="text/javascript">
/* global cleanHubitatDevices, resetHubitatSelectMenu, listHubitatDevices,
loadCredentials, paramsFromServer */
let sendEventChecked = true;
function listHubitatDeviceAttributes(server, deviceId, attribute) {
const selectMenu = resetHubitatSelectMenu('node-input-attribute', 'All');
$.getJSON(`hubitat/devices/${deviceId}`, paramsFromServer(server), (res) => {
const uniqueAttrs = res.attributes.reduce((accumulator, value) => {
if (!(value.name in accumulator)) {
accumulator[value.name] = value;
}
return accumulator;
}, {});
Object.values(uniqueAttrs).forEach((item) => {
selectMenu.append($('<option>', {
value: item.name,
text: item.name,
}));
});
if (attribute in uniqueAttrs) {
selectMenu.val(attribute).trigger('change');
}
});
}
function disableHubitatDeviceAttributes() {
const selectMenu = $('#node-input-attribute');
selectMenu.find('option').remove().end();
const option = $('<option>', { value: '', text: 'N/A' });
selectMenu.append(option);
selectMenu.val('').trigger('change');
selectMenu.prop('disabled', true);
}
function enableHubitatDeviceAttributes() {
const selectMenu = $('#node-input-attribute');
selectMenu.prop('disabled', false);
}
function disableSendEventCheckbox() {
const sendEventCheckbox = $('#node-input-sendEvent');
sendEventChecked = $('#node-input-sendEvent').is(':checked');
sendEventCheckbox.prop('checked', false);
sendEventCheckbox.prop('disabled', true);
}
function enableSendEventCheckbox() {
const sendEventCheckbox = $('#node-input-sendEvent');
sendEventCheckbox.prop('checked', sendEventChecked);
sendEventCheckbox.prop('disabled', false);
}
RED.nodes.registerType('hubitat device', {
category: 'hubitat',
color: '#ACE043',
defaults: {
deviceLabel: { value: '' },
name: { value: '' },
server: { type: 'hubitat config', required: true },
deviceId: { value: '' },
attribute: { value: '' },
sendEvent: { value: true },
},
inputs: 1,
outputs: 1,
icon: 'device.svg',
label() { return this.name || this.deviceLabel || 'device'; },
paletteLabel: 'device',
oneditprepare() {
$('document').ready(() => {
$('#node-input-deviceLabel').hide();
sendEventChecked = $('#node-input-sendEvent').is(':checked');
$('#node-input-server').change(() => {
const serverId = $('#node-input-server option:selected').val();
const server = RED.nodes.node(serverId);
if (server) {
loadCredentials(server).then(() => { listHubitatDevices(server, this.deviceId); });
} else {
cleanHubitatDevices();
}
});
$('#node-input-deviceId').change(() => {
const deviceLabel = $('#node-input-deviceId option:selected').text();
const deviceId = $('#node-input-deviceId option:selected').val();
if (deviceId) {
$('#node-input-name').attr('placeholder', deviceLabel);
if (!this.name) {
$('#node-input-deviceLabel').val(deviceLabel);
}
}
const serverId = $('#node-input-server option:selected').val();
const server = RED.nodes.node(serverId);
if (server && deviceId) {
enableHubitatDeviceAttributes();
enableSendEventCheckbox();
if (server.credentials) {
listHubitatDeviceAttributes(server, deviceId, this.attribute);
} else {
$.getJSON(`credentials/hubitat-config/${server.id}`, (data) => {
server.credentials = data;
server.credentials._ = $.extend(true, {}, data);
listHubitatDeviceAttributes(server, deviceId, this.attribute);
});
}
} else {
disableHubitatDeviceAttributes();
disableSendEventCheckbox();
$('#node-input-deviceLabel').val('');
$('#node-input-name').attr('placeholder', 'device');
}
});
$('#node-input-name').change(() => {
const name = $('#node-input-name').val();
const deviceId = $('#node-input-deviceId option:selected').val();
if ((!name) && (deviceId)) {
const deviceLabel = $('#node-input-deviceId option:selected').text();
$('#node-input-deviceLabel').val(deviceLabel);
}
});
});
},
});
</script>
<script type="text/html" data-template-name="hubitat device">
<div class="form-row">
<label for="node-input-server"><i class="fa fa-globe"></i> Server</label>
<input type="text" id="node-input-server">
</div>
<div class="form-row">
<label for="node-input-deviceId"><i class="fa fa-lightbulb-o"></i> Device</label>
<select id="node-input-deviceId"></select>
</div>
<div class="form-row">
<label for="node-input-attribute"><i class="fa fa-bars"></i> Attribute</label>
<select id="node-input-attribute"></select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-row">
<label for="node-input-sendEvent" style="width: auto"><i class="fa fa-rocket"></i> Send events </label>
<input type="checkbox" id="node-input-sendEvent" style="display: inline-block; width: auto; vertical-align: top;" checked>
</div>
<!-- to be handled by NR framework-->
<div class="form-row">
<label for="node-input-deviceLabel"></label>
<input type="text" id="node-input-deviceLabel">
</div>
</script>
<script type="text/html" data-help-name="hubitat device">
<p>A node that keep the current state of Hubitat device.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt class="optional">msg.deviceId <span class="property-type">string</span></dt>
<dd>Allow to overwrite the device.</dd>
</dl>
<dl class="message-properties">
<dt class="optional">msg.attribute <span class="property-type">string</span></dt>
<dd>If set, this is used to force the node to ouput the current state of this attribute</dd>
</dl>
<h3>Output</h3>
<dl class="message-properties">
<dt class="optional">msg.payload <span class="property-type">string</span></dt>
<dd>The attribute values. example:
<code>
{
payload: {
name: "switch",
value: "on",
dataType: "ENUM"
}
}
</code>
</dd>
</dl>
<h3>Details</h3>
<p>This node will keep device state. Every time the device state changes at Hubitat, the webhook will send us the current status.</p>
<p><b>Device</b> dropdown is populated when the server is reachable.</p>
<p><b>Attribute</b> dropdown is populated when <b>Device</b> is selected.
The <b>All</b> value allow to output all events and attributes.</p>
<p><b>Send events</b> allow to send or not event when it receive one from Hubitat.</p>
<p><code>currentValue</code> payload is deprecated and replaced by <code>value</code>.</p>
</script>