node-red-contrib-datacake-helpers
Version:
Node-RED nodes to interact with the Datacake GraphQL API for KPIs and device stats. Includes other helper nodes for device management.
129 lines (120 loc) • 5.26 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('datacakegraphql-device', {
category: 'Datacake',
color: '#3FADB5',
defaults: {
name: { value: "" },
datacakeConfig: { value: "", type: "datacakegraphql-config", required: true },
deviceId: { value: "", required: true },
availableDevices: { value: [] }
},
credentials: {},
inputs: 1,
outputs: 1,
icon: "icons/datacake.svg",
label: function() {
return this.name || "Datacake Device";
},
paletteLabel: "Device",
oneditprepare: function() {
const node = this;
const deviceSelect = $('#node-input-deviceId');
// Function to populate the device select dropdown
function populateDevices(devices) {
deviceSelect.empty();
deviceSelect.append('<option value="">Select a device</option>');
if (devices && devices.data && devices.data.allDevices) {
node.availableDevices = devices.data.allDevices;
devices.data.allDevices.forEach(device => {
const displayName = device.verboseName || device.serialNumber || device.id;
deviceSelect.append(`<option value="${device.id}">${displayName}</option>`);
});
// Set previously selected device
if (node.deviceId) {
deviceSelect.val(node.deviceId);
}
}
}
// Handle config node selection change
$('#node-input-datacakeConfig').on('change', function() {
const configNodeId = $(this).val();
if (configNodeId) {
$('#device-loading').show();
// Fetch devices from the selected config
$.getJSON('datacakegraphql/devices', { configId: configNodeId })
.done(function(devices) {
populateDevices(devices);
$('#device-loading').hide();
})
.fail(function(err) {
console.error('Error fetching devices:', err);
RED.notify(`Error fetching devices: ${err.responseJSON ? err.responseJSON.error : err.statusText}`, "error");
$('#device-loading').hide();
});
} else {
deviceSelect.empty();
deviceSelect.append('<option value="">Select a config first</option>');
}
});
// Trigger config node change if already selected
if (this.datacakeConfig) {
$('#node-input-datacakeConfig').trigger('change');
}
},
oneditsave: function() {
this.deviceId = $('#node-input-deviceId').val();
}
});
</script>
<script type="text/html" data-template-name="datacakegraphql-device">
<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-datacakeConfig"><i class="fa fa-cog"></i> Config</label>
<input type="text" id="node-input-datacakeConfig">
</div>
<div class="form-row">
<label for="node-input-deviceId"><i class="fa fa-microchip"></i> Device</label>
<select type="text" id="node-input-deviceId">
<option value="">Select a config first</option>
</select>
<span id="device-loading" style="margin-left: 10px; display: none;">
<i class="fa fa-spinner fa-spin"></i> Loading devices...
</span>
</div>
</script>
<script type="text/html" data-help-name="datacakegraphql-device">
<p>Node that fetches device data from the Datacake GraphQL API.</p>
<h3>Inputs</h3>
<dl class="message-properties">
<dt>payload <span class="property-type">any</span></dt>
<dd>Any input message will trigger a query to fetch the latest device data.</dd>
</dl>
<h3>Outputs</h3>
<dl class="message-properties">
<dt>payload <span class="property-type">object</span></dt>
<dd>A flattened object containing the device information and measurements.</dd>
</dl>
<h3>Details</h3>
<p>This node fetches data from a specific Datacake device and outputs a flattened structure that includes:</p>
<ul>
<li>Basic device information (id, serialNumber, verboseName, etc.)</li>
<li>All device measurements as top-level properties</li>
<li>Metadata for each measurement (field type, unit, etc.)</li>
</ul>
<p>Example output:</p>
<pre>{
"id": "device-uuid",
"serialNumber": "ABC123",
"verboseName": "My Device",
"TEMPERATURE": 25.4,
"TEMPERATURE_metadata": {
"id": "field-uuid",
"type": "FLOAT",
"unit": "°C"
},
...
}</pre>
</script>