UNPKG

iobroker.sonnen

Version:
303 lines (275 loc) 15.4 kB
/* ioBroker.vis sonnen Widget-Set version: "0.0.1" Copyright 2021 Moritz Heusinger moritz.heusinger@gmail.com */ 'use strict'; // add translations for edit mode $.extend( true, systemDictionary, { // Add your translations here, e.g.: 'sonnenMainColor': { 'en': 'primary color', 'de': 'Primärfarbe', 'ru': 'Основной цвет', 'pt': 'cor primária', 'nl': 'primaire kleur', 'fr': 'couleur primaire', 'it': 'colore primario', 'es': 'color primario', 'pl': 'kolor podstawowy', 'zh-cn': '原色' }, 'sonnenInstance': { 'en': 'adapter instance', 'de': 'Adapterinstanz', 'ru': 'экземпляр адаптера', 'pt': 'instância do adaptador', 'nl': 'adapter instantie', 'fr': "instance d'adaptateur", 'it': "istanza dell'adattatore", 'es': 'instancia de adaptador', 'pl': 'instancja adaptera', 'zh-cn': '适配器实例' }, 'sonnenStrokeWidth': { 'en': 'stroke width in px', 'de': 'Strichstärke in px', 'ru': 'ширина штриха в пикселях', 'pt': 'largura do traço em px', 'nl': 'lijnbreedte in px', 'fr': 'largeur de trait en px', 'it': 'larghezza del tratto in px', 'es': 'ancho del trazo en px', 'pl': 'szerokość obrysu w pikselach', 'zh-cn': '以 px 为单位的描边宽度' } } ); // this code can be placed directly in sonnen.html vis.binds['sonnen'] = { createWidget: function (widgetID, view, data, style) { let mainColor = data._data.sonnenMainColor || '#181A27'; let instance = data._data.sonnenInstance || 'sonnen.0'; let strokeWidth = !isNaN(parseInt(data._data.sonnenStrokeWidth)) ? data._data.sonnenStrokeWidth + 'px' : '8px'; let halfStrokeWidth = parseInt(strokeWidth) / 2 + 'px'; console.log(new Date().toLocaleTimeString() + ' sonnen[' + widgetID + ']: Trying to render widget'); let $div = $('#' + widgetID); // if nothing found => wait if (!$div.length) { return setTimeout(function () { vis.binds['sonnen'].createWidget(widgetID, view, data, style); }, 100); } let text = ''; text += '<div id="sonnen-grid"><svg class="sonnen-img" xmlns="http://www.w3.org/2000/svg" width="31" height="33" viewBox="0 0 31 33">\n' + ' <g fill="none" fill-rule="evenodd" stroke="' + mainColor + '" stroke-linecap="round" stroke-linejoin="round">\n' + ' <path d="M.5 32.5h30M25 32.5L18.523.5h-5.858L6 32.5M19.379 3.5H26.5M4.5 3.5H12M21 11.5h4.5M5.508 11.5H10"/>\n' + ' <path d="M19.5 6.5l-9.5 9 14 13"/>\n' + ' <path d="M11.5 6.5l9.5 9-14 13"/>\n' + ' </g>\n' + '</svg>\n</div>'; text += '<div id="sonnen-house"><svg class="sonnen-img" xmlns="http://www.w3.org/2000/svg" width="37" height="31" viewBox="0 0 37 31">\n' + ' <g fill="none" fill-rule="evenodd" stroke="' + mainColor + '" stroke-linecap="round" stroke-linejoin="round">\n' + ' <path d="M36.204 12.656L18.602.463 1 12.656"/>\n' + ' <path d="M6.5 9v21.5h4v-12h8v12h12V9"/>\n' + ' </g>\n' + '</svg>\n</div>'; text += '<div id="sonnen-battery"><svg class="sonnen-img" xmlns="http://www.w3.org/2000/svg" width="29" height="31" viewBox="0 0 29 31">\n' + ' <g fill="none" fill-rule="evenodd" stroke="' + mainColor + '">\n' + ' <rect width="28" height="30" x=".5" y=".5" rx="1"/>\n' + ' <path stroke-width=".9" d="M14.5 13.5c1.678 0 3.039-1.343 3.039-3s-1.36-3-3.039-3c-1.678 0-3.039 1.343-3.039 3s1.36 3 3.039 3z"/>\n' + ' <path stroke-linecap="round" d="M10.5 16.5h8"/>\n' + ' </g>\n' + '</svg>\n</div>'; text += '<div id="sonnen-photovoltaics"><svg class="sonnen-img" xmlns="http://www.w3.org/2000/svg" width="43" height="28" viewBox="0 0 43 28">\n' + ' <g fill="none" fill-rule="evenodd" stroke="' + mainColor + '" stroke-linejoin="round">\n' + ' <path d="M36.5.5h-30l-6 22h42z"/>\n' + ' <path stroke-width=".5" d="M21.5.5v22M12.5.5l-3 22M30.5.5l3 22"/>\n' + ' <path stroke-linecap="round" stroke-width=".5" d="M5.496 6h32.008M3.5 13h36"/>\n' + ' <path stroke-linecap="round" d="M31.5 22.602V27.5M11.5 22.5v5"/>\n' + ' </g>\n' + '</svg>\n</div>'; text += '<div id="sonnen-photovoltaics-line"> <svg class="sonnen-svg" height="100%" width="100%">\n' + ' <line id="sonnen-photovoltaics-line-svg" class="sonnen-line-svg" x1="0" y1="0" x2="0" y2="100%" />\n' + '</svg> </div>'; text += '<div id="sonnen-house-line"> <svg class="sonnen-svg" height="100%" width="100%">\n' + ' <line id="sonnen-house-line-svg" class="sonnen-line-svg" x1="0" y1="0" x2="0" y2="100%" />\n' + '</svg> </div>'; text += '<div id="sonnen-battery-line"> <svg class="sonnen-svg" height="100%" width="100%">\n' + ' <line id="sonnen-battery-line-svg" class="sonnen-line-svg" x1="0" y1="0" x2="100%" y2="0" />\n' + '</svg> </div>'; text += '<div id="sonnen-grid-line"> <svg class="sonnen-svg" height="100%" width="100%">\n' + ' <line id="sonnen-grid-line-svg" class="sonnen-line-svg" x1="0" y1="0" x2="100%" y2="0" />\n' + '</svg> </div>'; text += '<div class="sonnen-soc"><p class="sonnen-value" id="sonnen-soc-value"></p></div>'; text += '<div class="sonnen-consumption"><p class="sonnen-value" id="sonnen-consumption-value"></p></div>'; text += '<div class="sonnen-production"><p class="sonnen-value" id="sonnen-production-value"></p></div>'; text += '<div class="sonnen-grid"><p class="sonnen-value" id="sonnen-grid-value"></p></div>'; text += '<div class="sonnen-pac"><p class="sonnen-value" id="sonnen-pac-value"></p></div>'; $div.html(text); // cache all jQuery selectors let $sonnenGridLineSvg = $('#sonnen-grid-line-svg'); let $sonnenBatteryLineSvg = $('#sonnen-battery-line-svg'); let $sonnenPhotovoltaicsLine = $('#sonnen-photovoltaics-line'); let $sonnenHouseLine = $('#sonnen-house-line'); let $sonnenBatteryLine = $('#sonnen-battery-line'); let $sonnenGridLine = $('#sonnen-grid-line'); let $sonnenSocValue = $('#sonnen-soc-value'); let $sonnenConsumptionValue = $('#sonnen-consumption-value'); let $sonnenProductionValue = $('#sonnen-production-value'); let $sonnenGridValue = $('#sonnen-grid-value'); let $sonnenPacValue = $('#sonnen-pac-value'); // subscribe on updates of value, we can use obj, newVal, oldVal function onChange(obj, newVal) { let id = obj.type.split('.')[3]; switch (id) { case 'userSoc': $sonnenSocValue.text(newVal + ' %'); break; case 'consumption': $sonnenConsumptionValue.text(newVal + ' W'); break; case 'production': $sonnenProductionValue.text(newVal + ' W'); break; case 'gridFeedIn': $sonnenGridValue.text(newVal + ' W'); if (parseInt(newVal) > 0) { // positive means we are feeding in $sonnenGridLineSvg.css('animation', 'sonnen-dash 10s linear reverse infinite'); } else { $sonnenGridLineSvg.css('animation', 'sonnen-dash 10s linear infinite'); } break; case 'pacTotal': $sonnenPacValue.text(newVal + ' W'); break; case 'batteryCharging': if (newVal) { $sonnenBatteryLineSvg.css('animation', 'sonnen-dash 10s linear infinite'); } else { $sonnenBatteryLineSvg.css('animation', 'sonnen-dash 10s reverse linear infinite'); } break; case 'flowConsumptionBattery': case 'flowGridBattery': case 'flowConsumptionGrid': case 'flowProductionBattery': case 'flowConsumptionProduction': case 'flowProductionGrid': // if one on the flows changed we have to cross check so do it everytime if (!(vis.states[instance + '.status.flowConsumptionBattery.val'] || vis.states[instance + '.status.flowGridBattery.val'] || vis.states [instance + '.status.flowProductionBattery.val'])) { // no flow to battery disable line $sonnenBatteryLine.hide(); } else { $sonnenBatteryLine.show(); } if (!(vis.states[instance + '.status.flowConsumptionBattery.val'] || vis.states[instance + '.status.flowConsumptionGrid.val'] || vis.states[instance + '.status.flowConsumptionProduction.val'])) { // no consumption disable house line $sonnenHouseLine.hide(); } else { $sonnenHouseLine.show(); } if (!(vis.states[instance + '.status.flowProductionBattery.val'] || vis.states[instance + '.status.flowProductionGrid.val'] || vis.states[instance + '.status.flowConsumptionProduction.val'])) { // no production disable photovoltaics-line line $sonnenPhotovoltaicsLine.hide(); } else { $sonnenPhotovoltaicsLine.show(); } if (!(vis.states[instance + '.status.flowGridBattery.val'] || vis.states[instance + '.status.flowProductionGrid.val'] || vis.states[instance + '.status.flowConsumptionGrid.val'])) { // no grid disable photovoltaics-line line $sonnenGridLine.hide(); } else { $sonnenGridLine.show(); } break; default: console.error(new Date().toLocaleTimeString() + ' sonnen[' + widgetID + ']: objectChange unknown id: ' + id); } } let dps = [ instance + '.status.userSoc', instance + '.status.consumption', instance + '.status.production', instance + '.status.gridFeedIn', instance + '.status.pacTotal', instance + '.status.flowConsumptionBattery', instance + '.status.flowGridBattery', instance + '.status.flowConsumptionGrid', instance + '.status.flowProductionBattery', instance + '.status.flowConsumptionProduction', instance + '.status.flowProductionGrid', instance + '.status.batteryCharging' ]; // Update states and subscribe to changes vis.conn.getStates(dps, function (error, states) { console.log(new Date().toLocaleTimeString() + ' sonnen[' + widgetID + ']: Subscribing to state changes'); vis.updateStates(states); vis.conn.subscribe(dps); // ad onChange listener for (let i = 0; i < dps.length; i++) { dps[i] = dps[i] + '.val'; vis.states.bind(dps[i], onChange); } // endFor // give vis ability to destroy on change $div.data('bound', dps); $div.data('bindHandler', onChange); // set configured stroke width $sonnenPhotovoltaicsLine.css('width', strokeWidth); $sonnenPhotovoltaicsLine.css('left', 'calc(50% - '+ halfStrokeWidth + ')'); $sonnenHouseLine.css('width', strokeWidth); $sonnenHouseLine.css('left', 'calc(50% - '+ halfStrokeWidth + ')'); $sonnenBatteryLine.css('height', strokeWidth); $sonnenBatteryLine.css('bottom', 'calc(50% - '+ halfStrokeWidth + ')'); $sonnenGridLine.css('height', strokeWidth); $sonnenGridLine.css('bottom', 'calc(50% - '+ halfStrokeWidth + ')'); // set initial values $sonnenSocValue.text(states[instance + '.status.userSoc'].val + ' %'); $sonnenConsumptionValue.text(states[instance + '.status.consumption'].val + ' W'); $sonnenProductionValue.text(states[instance + '.status.production'].val + ' W'); $sonnenGridValue.text(states[instance + '.status.gridFeedIn'].val + ' W'); $sonnenPacValue.text(states[instance + '.status.pacTotal'].val + ' W'); // change color $('.sonnen-value').css('color', mainColor); if (!(states[instance + '.status.flowConsumptionBattery'].val || states[instance + '.status.flowGridBattery'].val || states [instance + '.status.flowProductionBattery'].val)) { // no flow to battery disable line $sonnenBatteryLine.hide(); } if (!(states[instance + '.status.flowConsumptionBattery'].val || states[instance + '.status.flowConsumptionGrid'].val || states[instance + '.status.flowConsumptionProduction'].val)) { // no consumption disable house line $sonnenHouseLine.hide(); } if (!(states[instance + '.status.flowProductionBattery'].val || states[instance + '.status.flowProductionGrid'].val || states[instance + '.status.flowConsumptionProduction'].val)) { // no production disable photovoltaics-line line $sonnenPhotovoltaicsLine.hide(); } if (!(states[instance + '.status.flowGridBattery'].val || states[instance + '.status.flowProductionGrid'].val || states[instance + '.status.flowConsumptionGrid'].val)) { // no grid disable photovoltaics-line line $sonnenGridLine.hide(); } // now add the animations if (states[instance + '.status.batteryCharging'].val) { $sonnenBatteryLineSvg.css('animation', 'sonnen-dash 10s linear infinite'); } else { $sonnenBatteryLineSvg.css('animation', 'sonnen-dash 10s reverse linear infinite'); } if (parseInt(states[instance + '.status.gridFeedIn'].val) > 0) { // positive means we are feeding in $sonnenGridLineSvg.css('animation', 'sonnen-dash 10s linear reverse infinite'); } else { $sonnenGridLineSvg.css('animation', 'sonnen-dash 10s linear infinite'); } }); } };