UNPKG

iobroker.enocean

Version:

Connects EnOcean devices via USB/Serial devices with TCM300 Chips

629 lines (536 loc) 20 kB
<html lang="EN"> <head> <!-- Load ioBroker scripts and styles--> <link rel="stylesheet" type="text/css" href="../../css/adapter.css" /> <link rel="stylesheet" type="text/css" href="../../lib/css/materialize.css"> <script type="text/javascript" src="../../lib/js/jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../../socket.io/socket.io.js"></script> <script type="text/javascript" src="../../js/translate.js"></script> <script type="text/javascript" src="../../lib/js/materialize.js"></script> <script type="text/javascript" src="../../js/adapter-settings.js"></script> <script type="text/javascript" src="../../lib/js/showdown.min.js"></script> <!-- Load our own files --> <link rel="stylesheet" type="text/css" href="style.css" /> <script type="text/javascript" src="words.js"></script> <script type="text/javascript" src="components.js"></script> <script type="text/javascript" src="github.js"></script> <script type="text/javascript"> let eepList, deviceList, sysConfig; let eepArray = []; let mfrArray = []; let deviceArray = []; let eepListFilled = false; let mfrListFilled = false; let devices = {}; let deviceCommands = { "delete": {} }; let instances; /** * Get available serial ports and add them to dropdown. If possible the port will be preselected. * @param {object} settings - The adapter settings object */ function getComPorts(settings) { sendTo(null, 'listSerial', null, (list) => { if (!list || !list.result) { return; } list = list.result; fillSelect('#serialport', list); $('#serialport.value').val(settings.serialport).select(); }); } /** * Load all devices, make the list global as array (only name) and object (name & id). */ function getDeviceList(){ sendTo(null, 'getDevices', null, (list) => { deviceList = list; //mfrArray.push(keys[i].replace(/_/g, ' ')); mfrArray = Object.keys(list); mfrArray.sort(); }) } /** * Load all EEP, make the list global as array (only name) and object (complete profile). */ function getEEPList(){ sendTo(null, 'getEEPList', null, (list) => { eepList = list; for(let i in eepList){ eepArray.push(eepList[i].eep); } }) } function fillEEPselect(){ if(eepListFilled === false){ fillSelect('#select-eep', eepArray); eepListFilled = true; $('#select-eep') .select() .change((option) => { let eep = option.target.value.replace(/-/g, ''); $('#device-name').val(eepList[eep].type_title); }); } } function fillMfrselect(){ if(mfrListFilled === false){ fillSelect('#select-manufacturer', mfrArray); mfrListFilled = true; $('#select-manufacturer').select(); } } function fillDeviceSelect(){ fillSelect('#select-device', deviceArray) $('#select-device').select(); } /** * List all known devices on devices tab. * @param {object} obj - ioBroker object for the device */ function showDevice(obj) { let text = ''; text += '<td >' + obj.native.id + '</td>'; if(obj.native.Sender_ID) { text += '<td >' + obj.native.Sender_ID + '</td>'; } else { text += '<td>' + '--' + '</td>'; } text += '<td>' + obj.native.eep + '</td>'; if(obj.native.manufacturer) { text += '<td>' + obj.native.manufacturer + '</td>'; } else { text += '<td>' + '--' + '</td>'; } if (obj.common.name) { text += '<td>' + obj.common.name + '</td>'; } else { text += '<td>' + '--' + '</td>'; } text += '<td>' + '' + '<a id="'+ obj.native.id + obj.common.role + '" class="delete-device values-buttons btn-floating btn-small waves-effect waves-light red"><i class="material-icons" title="Delete device">delete</i></a>'; for (let i in deviceCommands) { text += '<option value="' + i + '">' + _(i) + '</option>'; } text += '</select></td>'; text = '<tr data-id="' + obj.native.id + '">' + text + '</tr>'; $('#devices_body').append(text); $('#' + obj.native.id + obj.common.role).click(function(e){ sendTo('enocean.' + instance, 'deleteDevice', obj.native.id); // remove from list $(this).closest('tr').remove(); }); } function getDevices() { socket.emit('getObjectView', 'system', 'device', { startkey: 'enocean.' + instance + '.', endkey: 'enocean.' + instance + '.\u9999', include_docs: true }, function (err, _devices) { socket.emit('getStates', function (err, _values) { let namespace = 'enocean.' + instance + '.'; $('#devices_body').html(''); if (_devices && _devices.rows && _devices.rows.length) { for (let j = 0; j < _devices.rows.length; j++) { devices[_devices.rows[j].value._id] = _devices.rows[j].value; if(_devices.rows[j].value._id !== namespace + 'gateway'){ showDevice(_devices.rows[j].value); } } } }); }); } function loadSysConfig(){ socket.emit('getObject', 'system.config', function (err, res) { sysConfig = res; }); } function getGateway() { socket.emit('getObject', 'enocean.' + instance + '.gateway', function (err, res) { $('#BaseID').text(res.native.BaseID); }); } function getSystemInformation() { sendTo(null, 'getSystemInfo', null, (info) => { $('#systemInfo').text('``` \n' + JSON.stringify(info, undefined, 2) + '\n```'); }); } // Copy to clipboard function copyToClipboard(element) { navigator.clipboard.writeText(element); } //subscribe to lastID socket.emit('subscribe', 'enocean.' + instance + '.gateway.lastID'); socket.on('stateChange', function (id, state) { //console.log(state); if(id === 'enocean.' + instance + '.gateway.lastID'){ $('#lastID').text(state.val); } }); /** * Load the adapter config page. * @param {object} settings - The adapter settings * @param onChange - call this if there are settings changed that should be saved (will activate the save buttons) */ function load(settings, onChange) { loadSysConfig(); $('.modal').modal(); let selectorInputs = document.querySelectorAll('select'); instances = M.FormSelect.init(selectorInputs); if (settings.ser2net === false){ $('#ser2net-div').removeClass('hide'); $('#options-serialport-div').removeClass('hide'); } else { $('#ser2net-div').removeClass('hide'); $('#options-ser2net-ip-div').removeClass('hide'); $('#options-ser2net-port-div').removeClass('hide'); $('#ser2net-ip').val(settings['ser2net-ip']); $('#ser2net-port').val(settings['ser2net-port']); } $('#gateway') .val(settings.gateway) .on('change', () => { let $gateway = $('#gateway').val(); if( $gateway === 'usb300' || $gateway === 'fgw14-usb'){ $('#ser2net-div').removeClass('hide'); if(settings.ser2net === false){ $('#options-serialport-div').removeClass('hide'); $('#options-ser2net-ip-div').addClass('hide'); $('#options-ser2net-port-div').addClass('hide'); } else { $('#options-serialport-div').addClass('hide'); $('#options-ser2net-ip-div').removeClass('hide'); $('#options-ser2net-port-div').removeClass('hide'); $('#ser2net-ip').val(settings['ser2net-ip']); $('#ser2net-port').val(settings['ser2net-port']); } } if( $gateway === 'all-smart'|| $gateway === 'bsc-multigateway'){ $('#options-ser2net-ip-div').removeClass('hide'); $('#options-ser2net-port-div').removeClass('hide'); $('#ser2net-div').addClass('hide'); $('#options-serialport-div').addClass('hide'); } onChange(); }) // example: select elements with id=key and class=value and insert value if (!settings) return; $('.value').each(function () { let $key = $(this); let id = $key.attr('id'); if ($key.attr('type') === 'checkbox') { // do not call onChange direct, because onChange could expect some arguments $key.prop('checked', settings[id]) .on('change', () => onChange()); } else if($key.attr('class') === 'save'){ // do not call onChange direct, because onChange could expect some arguments $key.val(settings[id]) .on('change', () => onChange()) .on('keyup', () => onChange()); } }); showdown.setFlavor('github'); $('#ser2net').on('change', () => { if( $('#ser2net').prop('checked') === true ){ $('#options-serialport-div').addClass('hide'); $('#options-ser2net-ip-div').removeClass('hide'); $('#options-ser2net-port-div').removeClass('hide'); } else { $('#options-serialport-div').removeClass('hide'); $('#options-ser2net-ip-div').addClass('hide'); $('#options-ser2net-port-div').addClass('hide'); } setTimeout(function(){ onChange(); }, 100); }) $('#serialport').on('change', () => { onChange(); }) getComPorts(settings); //getmfrList(); getDeviceList(); getEEPList(); $('#addDevice').on('click', () => { fillEEPselect(); fillMfrselect(); $('#select-eep').on('change', () => { M.updateTextFields(); }) }); //fill devices by manufacturer $('#select-manufacturer').on('change', () => { let selected = $('#select-manufacturer').val(); deviceArray = Object.keys(deviceList[selected]) fillDeviceSelect(); }) //show additional fields for selected device $('#select-device').on('change', ()=>{ $('#help') .empty() .removeClass('hide'); const mfr = $('#select-manufacturer').val(); const dev = $('#select-device').val(); if(deviceList[mfr][dev].autocreate === false){ $('#div-id').removeClass('hide'); } else { $('#div-id').addClass('hide'); } const device = deviceList[mfr][dev].help[sysConfig.common.language]; for (let i in device) { let card = '<div class="col s12">\n' + '\t\t\t\t\t\t<div class="card light-blue lighten-4">\n' + '\t\t\t\t\t\t\t<div class="card-content black-text">\n' + '\t\t\t\t\t\t\t\t<span class="card-title">\n' + '\t\t\t\t\t\t\t\t<div class="col s2 translate">Step</div>\n' + '\t\t\t\t\t\t\t\t<div class="col s10 translate">' + i + '</div></span>\n' + '\t\t\t\t\t\t\t\t<p>' + device[i] + '</p>\n' + '\t\t\t\t\t\t\t</div>\n' + '\t\t\t\t\t\t</div>\n' + '\t\t\t\t\t</div>\n'; $('#help').append(card); } translateAll(); }) // Initialize copy-support-info button $('#copy-support-info').on('click', () => { let text = $('#systemInfo').text(); copyToClipboard(text); }); $('#addDeviceSubmit').on('click', () => { const manufacturer = $('#select-manufacturer').val(); const device = $('#select-device').val(); const name = device; if (deviceList[manufacturer][device].autocreate === false) { const deviceId = $('#device-id').val(); sendTo(null, 'newDevice', {device: name, mfr: manufacturer, id: deviceId}, (data) => { if (data.result === 'Ready') { getDevices(); } }); } else { sendTo(null, 'autodetect', {teachin_method: deviceList[manufacturer][device].teachin_method, device: name, mfr: manufacturer}, () => { setInterval( () => { getDevices(); }, 1000) }) } }); //make a device request /*$('#requestDeviceSubmit').on('click', () => { //window.open('https://github.com/Jey-Cee/ioBroker.enocean/issues?q=label%3A%22Device+request%22+'); deviceRequest($('#manufacturer').val(), $('#model').val(), $('#prod-date').val(), $('#link').val(), $('#additional').val()); })*/ // populate the list of known devices getDevices(); getGateway(); getSystemInformation(); onChange(false); // reinitialize all the Materialize labels on the page if you are dynamically adding inputs: if (M) M.updateTextFields(); $('#additional').keyup(() => { M.textareaAutoResize($('#additional')); }) } // This will be called by the admin adapter when the user presses the save button function save(callback) { // example: select elements with class=value and build settings object let obj = {}; $('.value').each(function () { let $this = $(this); if ($this.attr('type') === 'checkbox') { console.log($this.attr('id')); console.log($this.prop('checked')); obj[$this.attr('id')] = $this.prop('checked'); } else { obj[$this.attr('id')] = $this.val(); } }); callback(obj); } </script> </head> <body> <div class="m adapter-container"> <!-- Navbar --> <div class="row"> <div class="col s12"> <ul class="tabs"> <li class="tab col s2"><a href="#tab-devices" class="translate active">Devices</a></li> <li class="tab col s2"><a href="#tab-main" class="translate active">Settings</a></li> <li class="tab col s2"><a href="#tab-support-info" class="translate active">Support information</a></li> </ul> </div> <!-- Options Tab --> <div id="tab-main" class="col s12 page" style="height: 100%"> <div class="row"> <div class="col s12 m4 l2"> <img src="enocean.png" class="logo" style="height:7em; width: 7em;" alt="EnOcean"> </div> </div> <div class="row"> <div id="options-Gateway" class="input-field col s12 m6 l3"> <select id="gateway" class="value save" > <option value="">Select Gateway</option> <option value="usb300">USB300</option> <option value="usb300">EnOcean Pi</option> <option value="usb300">FAM-USB (ESP3 Firmware)</option> <option value="fgw14-usb">FGW14(-USB)</option> <option value="all-smart">ALL SMART EnOcean LAN Gateway</option> <option value="bsc-multigateway">BSC EnOcean Multigateway</option> </select> <label for="gateway" class="translate">Gateway</label> </div> </div> <div class="row"> <div id="ser2net-div" class="switch col s4 input-field hide" style="z-index: 10"> <label> USB/Serial <input id="ser2net" type="checkbox" class="value save"> <span class="lever"></span> Serial over network (Ser2Net) </label> </div> <div id="important" class="col s12 m12 l12"> <p class="translate">IMPORTANT: Use save button NOT save and close</p> </div> <div id="options-serialport-div" class="input-field col s12 m6 l3 hide"> <select id="serialport" class="value save" ></select> <label for="serialport" class="translate">Serial port</label> </div> <div id="options-ser2net-ip-div" class="input-field col s12 m6 l3 hide"> <input class="text value save" id="ser2net-ip" size="15" type="text"> <label class="translate active" for="ser2net-ip">IP</label> </div> <div id="options-ser2net-port-div" class="input-field col s12 m6 l3 hide"> <input class="text value save" id="ser2net-port" size="6" type="number"> <label class="translate active" for="ser2net-port">Port</label> </div> <div class="col s1"> <!-- spacer --> </div> <div class="switch col s4 input-field hide"> <label> Editor <input id="options-switch-editor" type="checkbox"> <span class="lever"></span> Attention: Use it at your own risk. </label> </div> </div> </div> <!-- Devices Tab --> <div id="tab-devices" class="col s12 page"> <div class="row"> <div class="input-field col"> <a id="addDevice" class="waves-effect waves-light btn modal-trigger translate" href="#add-device">Add new device</a> </div> <div class="col s2 push-s8"> <div class="card blue lighten-3"> <div class="card-content center-align" style="font-size: 1.3em;"> <span class="translate">Base ID: </span><span id="BaseID">ffffff</span> </div> </div> </div> </div> <div id="devices"> <table class="centered"> <thead> <tr> <th class="translate">ID</th> <th class="translate">Sender ID</th> <th class="translate">EEP</th> <th class="translate" data-lang="manufacturer">Manufacturer</th> <th class="translate" data-lang="device">Device</th> <th class="translate" ></th> </tr> </thead> <tbody id="devices_body" class="table-values"> </tbody> </table> </div> </div> <!-- Support information Tab --> <div id="tab-support-info" class="col s12 page"> <div class="row"> <div id="info-body" class="col s12"> <!-- Show support information as code with copy to clipboard button --> <div class="card"> <div class="card-content"> <span class="card-title translate">Support information</span> <pre id="systemInfo" class="support-info"></pre> </div> <div class="card-action"> <a id="copy-support-info" class="waves-effect waves-light btn translate" href="#">Copy to clipboard</a> </div> </div> </div> </div> </div> <!-- Add Device Modal Structure --> <div id="add-device" class="modal modal-fixed-footer"> <div class="modal-content"> <h5 class="translate center">Add new device</h5> <div class="row"> <div class="input-field col s5"> <select id="select-manufacturer"> <option value="" class="translate" disabled selected>Choose</option> </select> <label class="translate" for="select-manufacturer">manufacturer</label> </div> <div class="input-field col s5"> <select id="select-device"> <option value="" class="translate" disabled selected>Choose</option> </select> <label class="translate" for="select-device">device</label> </div> <div id="div-id" class="input-field col s2 hide"> <input id="device-id" class="value" type="text" placeholder="e.g. 0014A42D" minlength="8" maxlength="8"> <label for="device-id" class="translate">Device ID</label> </div> <div class="input-field col s12 hide"> <input id="device-name" class="value" type="text"> <label for="device-name" class="translate">Device Name</label> </div> <div class="input-field col s3 hide"> <select id="select-eep"> <option value="" class="translate" disabled selected>Choose</option> </select> <label for="select-eep">EEP</label> </div> </div> <div id="help" class="row hide"> </div> </div> <div class="row"> <div class="col s3 push-s9"> <div class="card blue lighten-3"> <div class="card-content center-align" style="padding:7px;"> <span class="translate">Last seen ID: </span><span id="lastID" style="font-size: 1.3em;">ffffff</span> </div> </div> </div> </div> <div class="modal-footer"> <div class="col" style="position:absolute; left: 15px;" > <a id="requestDevice" class="waves-effect waves-light btn modal-close modal-trigger translate" href="#request-device">Device not listed?</a> </div> <button id="addDeviceSubmit" class="btn waves-effect waves-light modal-close modal-action translate" type="submit" name="action">Add device</button> <button class="btn waves-effect waves-light modal-close modal-action translate" href="#!">Close</button> </div> </div> <!-- Request device --> <div id="request-device" class="modal modal-fixed-footer"> <div class="modal-content"> <h5 class="translate center">Request device integration</h5> <div class="row"> <p class="translate">Request Device Text</p> </div> </div> <div class="modal-footer"> <a href="https://github.com/Jey-Cee/ioBroker.enocean/issues/new?assignees=Jey-Cee&labels=Device+request&template=device-request.md&title=" target=”_blank”><button id="requestDeviceSubmit" class="btn waves-effect waves-light modal-close modal-action translate" type="submit" name="action">Send request</button></a> <button class="btn waves-effect waves-light modal-close modal-action translate" href="#!">Close</button> </div> </div> </div> </body> </html>