UNPKG

node-red-contrib-smartnora

Version:

Google Smart Home integration via Smart Nora https://smart-nora.eu/

329 lines (310 loc) 13.2 kB
<script type="text/javascript"> const SENSOR_TRAIT_AVAILABLE_SENSORS = [{ name: 'AirQuality', states: [ 'healthy', 'moderate', 'unhealthy', 'unhealthy for sensitive groups', 'very unhealthy', 'hazardous', 'good', 'fair', 'poor', 'very poor', 'severe' ], numeric: 'AQI' }, { name: 'CarbonMonoxideLevel', states: ['carbon monoxide detected', 'high', 'no carbon monoxide detected'], numeric: 'PARTS_PER_MILLION', }, { name: 'SmokeLevel', states: ['smoke detected', 'high', 'no smoke detected'], numeric: 'PARTS_PER_MILLION', }, { name: 'FilterCleanliness', states: ['clean', 'dirty', 'needs replacement'], numeric: null, }, { name: 'WaterLeak', states: ['leak', 'no leak'], numeric: null, }, { name: 'RainDetection', states: ['rain detected', 'no rain detected'], numeric: null, }, { name: 'FilterLifeTime', states: ['new', 'good', 'replace soon', 'replace now'], numeric: 'PERCENTAGE', }, { name: ['PreFilterLifeTime', 'HEPAFilterLifeTime', 'Max2FilterLifeTime'], states: null, numeric: 'PERCENTAGE', }, { name: 'CarbonDioxideLevel', states: null, numeric: 'PARTS_PER_MILLION', }, { name: ['PM2.5', 'PM10'], states: null, numeric: 'MICROGRAMS_PER_CUBIC_METER', }, { name: 'VolatileOrganicCompounds', states: null, numeric: 'PARTS_PER_MILLION', }]; RED.nodes.registerType('noraf-sensor', { category: 'nora', color: 'rgb(235, 227, 141)', icon: 'assistant.png', defaults: { devicename: { value: 'Sensor', required: true, }, roomhint: { value: '' }, name: { value: '' }, temperature: { value: false, }, unit: { value: 'C', validate: function (v) { return v === 'C' || v === 'F'; }, }, humidity: { value: false, }, passthru: { value: false, }, nora: { type: 'noraf-config', required: true }, topic: { value: '', }, filter: { value: false, }, sensorSupport: { value: false, }, sensorType: { value: 'AirQuality', }, sensorStates: { value: [], }, sensorStatesThatNotify: { value: [], }, sensorNumeric: { value: true, }, openCloseSupport: { value: false, }, openCloseDiscrete: { value: false, }, onOffSupport: { value: false, }, }, inputs: 1, outputs: 0, paletteLabel: 'sensor', label: function () { return this.name || this.devicename || 'sensor'; }, oneditprepare: function () { if ((this.unit || 'C') === 'C') { $('#unit-celsius').prop('checked', true); } else { $('#unit-fahrenheit').prop('checked', true); } $('#node-input-temperature').change(function () { $('.temperature-support')[$(this).is(':checked') ? 'show' : 'hide'](); }); $('#node-input-sensorSupport').change(function () { $('.sensor-support')[$(this).is(':checked') ? 'show' : 'hide'](); }); $('#node-input-openCloseSupport').change(function () { $('.openclose-support')[$(this).is(':checked') ? 'show' : 'hide'](); }); const selectedStates = this.sensorStates || []; const selectedSensorStatesThatNotify = this.sensorStatesThatNotify || []; $('#node-input-sensorType').change(function () { const selectedType = $(this).val(); const found = SENSOR_TRAIT_AVAILABLE_SENSORS.find(s => s.name === selectedType || s.name.includes(selectedType)) || {}; $('#states-container > *').remove(); $('.sensor-states')[found.states ? 'show' : 'hide'](); $('.sensor-numeric')[found.states && found.numeric ? 'show' : 'hide'](); if (!Array.isArray(found.states)) return; const stateContainer = $('#states-container'); stateContainer.html('<strong>On</strong><strong>Value</strong><strong>Notification</strong>'); for (const [index, state] of found.states.entries()) { $('<input/>', { id: `state-${index}`, type: 'checkbox', 'data-state': state, class: 'sensor-state', checked: selectedStates.includes(state), state, }) .text(state) .appendTo(stateContainer); $('<label/>', { for: `state-${index}`, }).html(`<code>${state}</code>`).appendTo(stateContainer); $('<input/>', { id: `state-${index}`, type: 'checkbox', 'data-notification-state': state, class: 'sensor-notification-state', checked: selectedSensorStatesThatNotify.includes(state), state, }) .text(state) .appendTo(stateContainer); } }); }, oneditsave: function () { this.unit = $('#unit-celsius').prop('checked') ? 'C' : 'F'; const sensorStates = []; const sensorStatesThatNotify = []; $('.sensor-state:checked').each(function () { sensorStates.push($(this).attr('data-state')); }); $('.sensor-notification-state:checked').each(function () { sensorStatesThatNotify.push($(this).attr('data-notification-state')); }); this.sensorStates = sensorStates; this.sensorStatesThatNotify = sensorStatesThatNotify; }, }); </script> <script type="text/x-red" data-template-name="noraf-sensor"> <style> #states-container { display: grid; grid-template-columns: auto 1fr auto; gap: 5px 15px; align-items: center; } #states-container input[type=checkbox] { width: unset; margin: 0; } #states-container input[data-notification-state] { justify-self: end; } #states-container label { width: unset; margin: 0; } .trait-support { margin-left: 5px; border-left: 1px solid lightgray; padding-left: 10px; padding-top: 10px; margin-top: -15px; margin-bottom: 5px; } </style> <div class="form-row"> <label for="node-input-nora"><i class="fa fa-table"></i> Config</label> <input type="text" id="node-input-nora"> </div> <div class="form-row"> <label for="node-input-devicename"><i class="fa fa-i-cursor"></i> Sensor</label> <input type="text" id="node-input-devicename"> </div> <div class="form-row"> <label style="width:auto" for="node-input-filter"><i class="fa fa-filter"></i> Ignore input messages that don't match the <code>topic</code> value: </label> <input type="checkbox" id="node-input-filter" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row"> <label style="width:auto" for="node-input-temperature"><i class="fa fa-thermometer-half"></i> Temperature </label> <input type="checkbox" id="node-input-temperature" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="temperature-support trait-support"> <div class="form-row"> <label style="width:auto"><i class="fa fa-thermometer-half"></i> Temperature Unit: </label> <input style="width:auto;margin:0" id="unit-celsius" type="radio" name="unit" value="C"><label style="width:40px" for="unit-celsius">&nbsp;C</label> <input style="width:auto;margin:0" id="unit-fahrenheit" type="radio" name="unit" value="F"><label style="width:40px" for="unit-fahrenheit">&nbsp;F</label> </div> </div> <div class="form-row"> <label style="width:auto" for="node-input-humidity"><i class="fa fa-percent"></i> Humidity </label> <input type="checkbox" id="node-input-humidity" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row"> <label style="width:auto" for="node-input-onOffSupport"><i class="fa fa-power-off"></i> On/Off </label> <input type="checkbox" id="node-input-onOffSupport" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row"> <label style="width:auto" for="node-input-openCloseSupport"><i class="fa fa-folder-open-o"></i> Open/close </label> <input type="checkbox" id="node-input-openCloseSupport" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="openclose-support trait-support"> <div class="form-row"> <label style="width:auto" for="node-input-openCloseDiscrete"><i class="fa fa-arrow-right"></i> Discrete only open/close: </label> <input type="checkbox" id="node-input-openCloseDiscrete" style="display:inline-block; width:auto; vertical-align:top;"> </div> </div> <div class="form-row"> <label style="width:auto" for="node-input-sensorSupport"><i class="fa fa-barcode"></i> Sensor </label> <input type="checkbox" id="node-input-sensorSupport" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="sensor-support trait-support"> <div class="form-row"> <label for="node-input-sensorType"><i class="fa fa-i-cursor"></i> Type</label> <select id="node-input-sensorType"> <option value="AirQuality">Air Quality</option> <option value="CarbonDioxideLevel">Carbon Dioxide Level</option> <option value="CarbonMonoxideLevel">Carbon Monoxide Level</option> <option value="FilterCleanliness">Filter Cleanliness</option> <option value="FilterLifeTime">Filter Life Time</option> <option value="PreFilterLifeTime">Filter Life Time (Pre)</option> <option value="HEPAFilterLifeTime">Filter Life Time (HEPA)</option> <option value="Max2FilterLifeTime">Filter Life Time (Max 2)</option> <option value="PM2.5">PM2.5</option> <option value="PM10">PM10</option> <option value="RainDetection">Rain Detection</option> <option value="SmokeLevel">Smoke Level</option> <option value="VolatileOrganicCompounds">Volatile Organic Compounds</option> <option value="WaterLeak">Water Leak</option> </select> </div> <div class="form-row sensor-numeric"> <label style="width:auto" for="node-input-sensorNumeric"><i class="fa fa-sort-numeric-desc"></i> Numeric capability </label> <input type="checkbox" id="node-input-sensorNumeric" style="display:inline-block; width:auto; vertical-align:top;"> </div> <div class="form-row sensor-states"> <label style="width:100%"><i class="fa fa-cog"></i> Supported states</label> <div id="states-container"></div> </div> </div> <div class="form-row"> <label for="node-input-roomhint"><i class="fa fa-i-cursor"></i> Room Hint</label> <input type="text" id="node-input-roomhint"> </div> <div class="form-row"> <label for="node-input-topic" style="padding-left:25px; margin-right:-25px">Topic</label> <input type="text" id="node-input-topic"> </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"> </div> </script> <script type="text/x-red" data-help-name="noraf-sensor"> <p> <a href="https://github.com/andrei-tatar/node-red-contrib-smartnora/blob/master/doc/nodes/sensor/README.md">https://github.com/andrei-tatar/node-red-contrib-smartnora/blob/master/doc/nodes/sensor/README.md</a> </p> </script>