node-red-contrib-dali-sensor
Version:
Node-RED node for parsing DALI sensor data and outputting motion and lux
128 lines (115 loc) • 5.29 kB
HTML
<script type="text/javascript">
RED.nodes.registerType('dali-sensor', {
category: 'input',
color: '#a4a4a4',
defaults: {
name: { value: '' },
shortAddress: { value: '1', required: true },
motionInstance: { value: 0, required: false, validate: RED.validators.number() },
luxInstance: { value: 1, required: false, validate: RED.validators.number() },
luxSetpoint: { value: 400, required: true, validate: RED.validators.number() },
useBoolean: { value: true },
/* new */
enableAutoOff: { value: false },
autoOffDelaySec: { value: 30, validate: v => !isNaN(v) && Number(v) > 0 }
},
inputs: 1,
outputs: 3,
outputLabels: ['Motion','Lux Value','Lux Alarm'],
icon: 'sensor.png',
label: function() {
var addr = this.shortAddress || '?';
var base = this.name || 'DALI Sensor';
return base + ' [' + addr + ']';
},
oneditprepare: function() {
var node = this;
$('#node-input-name').val(node.name);
$('#node-input-shortAddress').val(node.shortAddress);
$('#node-input-motionInstance').val(node.motionInstance);
$('#node-input-luxInstance').val(node.luxInstance);
$('#node-input-luxSetpoint').val(node.luxSetpoint);
$('#node-input-useBoolean').prop('checked', node.useBoolean);
// ---- Auto Off UI wiring
const $chk = $('#node-input-enableAutoOff');
const $delay = $('#node-input-autoOffDelaySec');
if ($delay.val() === '' || $delay.val() == null) $delay.val(30);
function syncAutoOffUI() {
const on = !!$chk.prop('checked');
$delay.prop('disabled', !on);
$('#autooff-help').toggle(on); // show short hint only when active
}
$chk.on('change', syncAutoOffUI);
syncAutoOffUI();
}
});
</script>
<script type="text/html" data-template-name="dali-sensor">
<style>
/* tiny helper styles to align checkboxes & inputs neatly */
.af-inline { display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
.af-inline .units { color:#888; }
.muted { color:#888; font-size:11px; }
.w-100 { width:100%; }
.w-8rem { width:8rem; }
.no-wrap { white-space:nowrap; }
</style>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" class="w-100"/>
</div>
<div class="form-row">
<label for="node-input-shortAddress"><i class="fa fa-hashtag"></i> Short Address</label>
<input type="text" id="node-input-shortAddress" class="w-8rem"/>
</div>
<div class="form-row">
<label for="node-input-motionInstance"><i class="fa fa-arrows-alt"></i> Motion Instance</label>
<input type="number" id="node-input-motionInstance" class="w-8rem"/>
</div>
<div class="form-row">
<label for="node-input-luxInstance"><i class="fa fa-sun-o"></i> Lux Instance</label>
<input type="number" id="node-input-luxInstance" class="w-8rem"/>
</div>
<div class="form-row">
<label for="node-input-luxSetpoint"><i class="fa fa-adjust"></i> Lux Setpoint</label>
<input type="number" id="node-input-luxSetpoint" class="w-8rem"/>
</div>
<div class="form-row">
<label for="node-input-useBoolean"><i class="fa fa-toggle-off"></i> Use Boolean</label>
<div class="af-inline">
<input type="checkbox" id="node-input-useBoolean">
<span class="muted">Output <code>true/false</code> instead of <code>On/Off</code></span>
</div>
</div>
<!-- Auto Off: single tidy row with checkbox + timeout + units -->
<div class="form-row">
<label for="node-input-enableAutoOff"><i class="fa fa-clock-o"></i> Auto Off</label>
<div class="af-inline">
<input type="checkbox" id="node-input-enableAutoOff">
<input type="number" id="node-input-autoOffDelaySec" min="1" step="1" class="w-8rem">
<span class="units no-wrap">seconds</span>
<span id="autooff-help" class="muted">On immediately / Off after delay (non-resettable)</span>
</div>
</div>
</script>
<script type="text/html" data-help-name="dali-sensor">
<p>This node parses DALI sensor frames (Device or Device/Instance schemes) and outputs:</p>
<ul>
<li><b>Motion</b>: latched occupancy state (On/Off or true/false)</li>
<li><b>Lux Value</b>: raw integer lux reading</li>
<li><b>Lux Alarm</b>: whether lux < setpoint (On/Off or true/false)</li>
</ul>
<p>Configure:</p>
<ul>
<li><code>shortAddress</code> to filter your device</li>
<li><code>motionInstance</code> & <code>luxInstance</code> numbers to map instances (Instance scheme) or types (Device scheme)</li>
<li><code>luxSetpoint</code> threshold</li>
<li><code>useBoolean</code> to switch outputs between boolean or "On"/"Off"</li>
</ul>
<h3>Auto Off (optional)</h3>
<ul>
<li>Motion output turns <b>On immediately</b> and <b>Off after the configured delay</b> (non-resettable).</li>
<li>Additional Off frames do not extend the countdown; an On cancels it.</li>
<li><code>msg.delay</code> (ms) can override the timeout when the countdown starts.</li>
</ul>
</script>