diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..b1f735e --- /dev/null +++ b/.eslintrc @@ -0,0 +1,19 @@ +{ + "rules": { + "comma-dangle": 0, + "indent": [2, 4], + "max-len": "off", + "radix": [2, "as-needed"], + "no-console": 0, + "linebreak-style": "off", + "prettier/prettier": 0 + }, + "settings": { + "import/core-modules": [ "node_helper" ] + }, + "env": { + "browser": true, + "node": true, + "es6": true + } +} diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml new file mode 100644 index 0000000..f4000e6 --- /dev/null +++ b/.github/workflows/nodejs.yml @@ -0,0 +1,28 @@ +# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node +# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions + +name: Node.js CI + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [10.x, 12.x, 14.x] + + steps: + - uses: actions/checkout@v2 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + - run: npm ci + - run: npm run build --if-present diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..681f42e --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,8 @@ +{ + "default": true, + "no-duplicate-header": { + "siblings_only": true + }, + "line-length": false, + "no-inline-html": false +} diff --git a/CHANGELOG.md b/CHANGELOG.md index af482e7..06017d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,32 +1,46 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [1.1.2] - 2020-04-08 + ### Fixed + - Fixed which property was being read to determine whether heat mode was enabled or not. Previously the state of the heater itself was being used to display on/off status, now the requested mode is used instead (the heater toggles on/off as part of normal operation even while heating is enabled). ## [1.1.1] - 2020-04-07 + ### Added + - Ability to specify which heat mode to use when enabling heating for a specific body. Previously mode 1 was always sent which means "solar" while most people probably want mode 3 which is "heat pump". ## [1.1.0] - 2020-04-01 + ### Added + - Ability to show buttons for controlling pool equipment (with a touch screen, for example). NOTE: running `npm install` again is necessary after upgrading to this version if the heat controls are used. ## [1.0.3] - 2018-04-27 + ### Changed + - Packaged a newer `node-screenlogic` dependency to fix server broadcast in certain environments. ## [1.0.2] - 2018-04-26 + ### Added + - New option `updateInterval` to control how often the pool data is updated (default 30 minutes). ## [1.0.1] - 2018-04-25 + ### Added + - New option `showFreezeMode` shows a banner acrosss the top if the pool is currently in freeze-protection mode. ## [1.0.0] - 2018-04-24 + - Initial release. diff --git a/MMM-ScreenLogic.js b/MMM-ScreenLogic.js index 701ae67..a2ac9c4 100644 --- a/MMM-ScreenLogic.js +++ b/MMM-ScreenLogic.js @@ -1,288 +1,288 @@ -poolData = {}; -var moduleObj; +let poolData = {}; +let moduleObj; Module.register("MMM-ScreenLogic",{ - defaults: { - showPoolTemp: true, - showSpaTemp: true, - showPH: true, - showOrp: true, - showSaltLevel: true, - showSaturation: true, - showFreezeMode: true, - showControls: false, - controls: [], - colored: true, - coldTemp: 84, - hotTemp: 90, - columns: 3, - contentClass: "light", - updateInterval: 30 * 60 * 1000 - }, + defaults: { + showPoolTemp: true, + showSpaTemp: true, + showPH: true, + showOrp: true, + showSaltLevel: true, + showSaturation: true, + showFreezeMode: true, + showControls: false, + controls: [], + colored: true, + coldTemp: 84, + hotTemp: 90, + columns: 3, + contentClass: "light", + updateInterval: 30 * 60 * 1000 + }, - start: function() { - // this isn't a great solution...is there a better one? needed to do stuff with buttons - moduleObj = this; - if (this.config.showControls && (!this.config.controls || this.config.controls.length == 0)) { - Log.warn('Controls are enabled, but no controls are configured. See README for info on setting up controls.'); - this.config.showControls = false; - } + start: function() { + // this isn't a great solution...is there a better one? needed to do stuff with buttons + moduleObj = this; + if (this.config.showControls && (!this.config.controls || this.config.controls.length === 0)) { + Log.warn('Controls are enabled, but no controls are configured. See README for info on setting up controls.'); + this.config.showControls = false; + } - this.sendSocketNotification('SCREENLOGIC_CONFIG', this.config); - this.sendSocketNotification('SCREENLOGIC_UPDATE'); - }, + this.sendSocketNotification('SCREENLOGIC_CONFIG', this.config); + this.sendSocketNotification('SCREENLOGIC_UPDATE'); + }, - getStyles: function() { - return ["screenlogic.css"]; - }, + getStyles: function() { + return ["screenlogic.css"]; + }, - getDom: function() { - if (!poolData.status) { - var wrapper = document.createElement("div"); - wrapper.innerHTML = 'Loading...'; - wrapper.className += "dimmed light small"; + getDom: function() { + if (!poolData.status) { + let wrapper = document.createElement("div"); + wrapper.innerHTML = 'Loading...'; + wrapper.className += "dimmed light small"; - return wrapper; - } else { - var table = document.createElement('table'); - table.className = "small"; - if (this.config.colored) { - table.className += " colored"; - } + return wrapper; + } else { + let table = document.createElement('table'); + table.className = "small"; + if (this.config.colored) { + table.className += " colored"; + } - var contents = []; + let contents = []; - if (this.config.showPoolTemp) { - var className = ""; - if (poolData.status.currentTemp[0] <= this.config.coldTemp) { - className += " cold-temp"; - } else if (poolData.status.currentTemp[0] >= this.config.hotTemp) { - className += " hot-temp"; - } + if (this.config.showPoolTemp) { + let className = ""; + if (poolData.status.currentTemp[0] <= this.config.coldTemp) { + className += " cold-temp"; + } else if (poolData.status.currentTemp[0] >= this.config.hotTemp) { + className += " hot-temp"; + } - contents.push({ - header: "Pool temp", - data: poolData.status.currentTemp[0] + "°" + (!isPoolActive(poolData.status) ? " (last)" : ""), - class: this.config.contentClass + className - }); - } - if (this.config.showSpaTemp) { - var className = ""; - if (poolData.status.currentTemp[1] <= this.config.coldTemp) { - className = " cold-temp"; - } else if (poolData.status.currentTemp[1] >= this.config.hotTemp) { - className = " hot-temp"; - } + contents.push({ + header: "Pool temp", + data: poolData.status.currentTemp[0] + "°" + (!isPoolActive(poolData.status) ? " (last)" : ""), + class: this.config.contentClass + className + }); + } + if (this.config.showSpaTemp) { + let className = ""; + if (poolData.status.currentTemp[1] <= this.config.coldTemp) { + className = " cold-temp"; + } else if (poolData.status.currentTemp[1] >= this.config.hotTemp) { + className = " hot-temp"; + } - contents.push({ - header: "Spa temp", - data: poolData.status.currentTemp[1] + "°" + (!isSpaActive(poolData.status) ? " (last)" : ""), - class: this.config.contentClass + className - }); - } - if (this.config.showPH) { - contents.push({ - header: "pH", - data: poolData.status.pH, - class: this.config.contentClass - }); - } - if (this.config.showOrp) { - contents.push({ - header: "ORP", - data: poolData.status.orp, - class: this.config.contentClass - }); - } - if (this.config.showSaltLevel) { - contents.push({ - header: "Salt PPM", - data: poolData.status.saltPPM, - class: this.config.contentClass - }); - } - if (this.config.showSaturation) { - contents.push({ - header: "Saturation", - data: poolData.status.saturation, - class: this.config.contentClass - }); - } - if (this.config.showControls) { - for (var control in this.config.controls) { - var controlObj = this.config.controls[control]; + contents.push({ + header: "Spa temp", + data: poolData.status.currentTemp[1] + "°" + (!isSpaActive(poolData.status) ? " (last)" : ""), + class: this.config.contentClass + className + }); + } + if (this.config.showPH) { + contents.push({ + header: "pH", + data: poolData.status.pH, + class: this.config.contentClass + }); + } + if (this.config.showOrp) { + contents.push({ + header: "ORP", + data: poolData.status.orp, + class: this.config.contentClass + }); + } + if (this.config.showSaltLevel) { + contents.push({ + header: "Salt PPM", + data: poolData.status.saltPPM, + class: this.config.contentClass + }); + } + if (this.config.showSaturation) { + contents.push({ + header: "Saturation", + data: poolData.status.saturation, + class: this.config.contentClass + }); + } + if (this.config.showControls) { + for (let control in this.config.controls) { + let controlObj = this.config.controls[control]; - if (controlObj.type === 'circuit') { - var name = controlObj.name; - for (var circuit in poolData.controllerConfig.bodyArray) { - if (poolData.controllerConfig.bodyArray[circuit].circuitId == controlObj.id) { - if (!name) { - name = poolData.controllerConfig.bodyArray[circuit].name; - } - } - } + if (controlObj.type === 'circuit') { + let name = controlObj.name; + for (let circuit in poolData.controllerConfig.bodyArray) { + if (poolData.controllerConfig.bodyArray[circuit].circuitId === controlObj.id) { + if (!name) { + name = poolData.controllerConfig.bodyArray[circuit].name; + } + } + } - var on = false; - for (var circuit in poolData.status.circuitArray) { - if (poolData.status.circuitArray[circuit].id == controlObj.id) { - on = poolData.status.circuitArray[circuit].state !== 0; - } - } + let on = false; + for (let circuit in poolData.status.circuitArray) { + if (poolData.status.circuitArray[circuit].id === controlObj.id) { + on = poolData.status.circuitArray[circuit].state !== 0; + } + } - var cls = ''; - if (this.config.colored) { - cls = on ? 'control-on' : 'control-off'; - } + let cls = ''; + if (this.config.colored) { + cls = on ? 'control-on' : 'control-off'; + } - contents.push({ - data: '', - class: this.config.contentClass - }); - } else if (controlObj.type === 'heatpoint') { - if (controlObj.body < 0 || controlObj.body > poolData.status.setPoint.length) { - Log.warn('Invalid body specified for heatpoint'); - continue; - } + class: this.config.contentClass + }); + } else if (controlObj.type === 'heatpoint') { + if (controlObj.body < 0 || controlObj.body > poolData.status.setPoint.length) { + Log.warn('Invalid body specified for heatpoint'); + continue; + } - var temperature = poolData.status.setPoint[controlObj.body]; + let temperature = poolData.status.setPoint[controlObj.body]; - var dataHtml = '
'; - dataHtml += ''; - dataHtml += '
'+controlObj.name+': '+temperature+'°
'; - dataHtml += ''; + let dataHtml = '
'; + dataHtml += ''; + dataHtml += '
'+controlObj.name+': '+temperature+'°
'; + dataHtml += ''; - contents.push({ - data: dataHtml, - class: this.config.contentClass - }); - } else if (controlObj.type === 'heatmode') { - if (controlObj.body < 0 || controlObj.body > poolData.status.heatMode.length) { - Log.warn('Invalid body specified for heatmode'); - continue; - } + contents.push({ + data: dataHtml, + class: this.config.contentClass + }); + } else if (controlObj.type === 'heatmode') { + if (controlObj.body < 0 || controlObj.body > poolData.status.heatMode.length) { + Log.warn('Invalid body specified for heatmode'); + continue; + } - var on = poolData.status.heatMode[controlObj.body] !== 0; - var mode = typeof controlObj.heatMode === 'number' ? controlObj.heatMode : 3; + let on = poolData.status.heatMode[controlObj.body] !== 0; + let mode = typeof controlObj.heatMode === 'number' ? controlObj.heatMode : 3; - var cls = ''; - if (this.config.colored) { - cls = on ? 'control-on' : 'control-off'; - } + let cls = ''; + if (this.config.colored) { + cls = on ? 'control-on' : 'control-off'; + } - contents.push({ - data: '', - class: this.config.contentClass - }); - } else { - Log.warn('circuit with unknown type, unable to display:'); - Log.warn(controlObj); - } - } - } + class: this.config.contentClass + }); + } else { + Log.warn('circuit with unknown type, unable to display:'); + Log.warn(controlObj); + } + } + } - var headerRow = null; - var contentRow = null; + let headerRow = null; + let contentRow = null; - if (this.config.showFreezeMode && poolData.status.freezeMode !== 0) { - var row = document.createElement('tr'); - table.appendChild(row); - row.className = 'cold-temp'; - var cell = document.createElement('th'); - row.appendChild(cell); - cell.colSpan = this.config.columns; - cell.innerHTML = '
FREEZE MODE
'; - } + if (this.config.showFreezeMode && poolData.status.freezeMode !== 0) { + let row = document.createElement('tr'); + table.appendChild(row); + row.className = 'cold-temp'; + let cell = document.createElement('th'); + row.appendChild(cell); + cell.colSpan = this.config.columns; + cell.innerHTML = '
FREEZE MODE
'; + } - var cols = -1; - for (var item in contents) { - cols++; - if (cols % this.config.columns === 0) { - headerRow = document.createElement('tr'); - contentRow = document.createElement('tr'); - table.appendChild(headerRow); - table.appendChild(contentRow); - } + let cols = -1; + for (let item in contents) { + cols++; + if (cols % this.config.columns === 0) { + headerRow = document.createElement('tr'); + contentRow = document.createElement('tr'); + table.appendChild(headerRow); + table.appendChild(contentRow); + } - if (contents[item].header) { - var headerCell = document.createElement('th'); - headerCell.innerHTML = contents[item].header; - headerRow.appendChild(headerCell); - } + if (contents[item].header) { + let headerCell = document.createElement('th'); + headerCell.innerHTML = contents[item].header; + headerRow.appendChild(headerCell); + } - var contentCell = document.createElement('td'); - contentCell.innerHTML = contents[item].data; - contentCell.className = contents[item].class; - contentRow.appendChild(contentCell); - } + let contentCell = document.createElement('td'); + contentCell.innerHTML = contents[item].data; + contentCell.className = contents[item].class; + contentRow.appendChild(contentCell); + } - return table; - } - }, + return table; + } + }, - socketNotificationReceived: function(notification, payload) { - if (notification === 'SCREENLOGIC_RESULT') { - poolData = payload; - this.updateDom(); - } else if (notification === 'SCREENLOGIC_CIRCUIT_DONE' + socketNotificationReceived: function(notification, payload) { + if (notification === 'SCREENLOGIC_RESULT') { + poolData = payload; + this.updateDom(); + } else if (notification === 'SCREENLOGIC_CIRCUIT_DONE' || notification === 'SCREENLOGIC_HEATSTATE_DONE' || notification === 'SCREENLOGIC_HEATPOINT_DONE') { - poolData.status = payload.status; - this.updateDom(); - } - }, + poolData.status = payload.status; + this.updateDom(); + } + }, }); const SPA_CIRCUIT_ID = 500; const POOL_CIRCUIT_ID = 505; function isPoolActive(status) { - for (var i = 0; i < status.circuitArray.length; i++) { - if (status.circuitArray[i].id === POOL_CIRCUIT_ID) { - return status.circuitArray[i].state === 1; - } - } + for (let i = 0; i < status.circuitArray.length; i++) { + if (status.circuitArray[i].id === POOL_CIRCUIT_ID) { + return status.circuitArray[i].state === 1; + } + } } function hasSpa(status) { - for (var i = 0; i < status.circuitArray.length; i++) { - if (status.circuitArray[i].id === SPA_CIRCUIT_ID) { - return true; - } - } + for (let i = 0; i < status.circuitArray.length; i++) { + if (status.circuitArray[i].id === SPA_CIRCUIT_ID) { + return true; + } + } - return false; + return false; } function isSpaActive(status) { - for (var i = 0; i < status.circuitArray.length; i++) { - if (status.circuitArray[i].id === SPA_CIRCUIT_ID) { - return status.circuitArray[i].state === 1; - } - } + for (let i = 0; i < status.circuitArray.length; i++) { + if (status.circuitArray[i].id === SPA_CIRCUIT_ID) { + return status.circuitArray[i].state === 1; + } + } } function setCircuit(e) { - var circuitId = parseInt(e.dataset.circuit); - var on = e.dataset.state !== '0'; - moduleObj.sendSocketNotification('SCREENLOGIC_CIRCUIT', {id: circuitId, state: on ? 0 : 1}); - e.classList.remove('control-on', 'control-off'); + let circuitId = parseInt(e.dataset.circuit); + let on = e.dataset.state !== '0'; + moduleObj.sendSocketNotification('SCREENLOGIC_CIRCUIT', {id: circuitId, state: on ? 0 : 1}); + e.classList.remove('control-on', 'control-off'); } function setHeatmode(e) { - var bodyId = parseInt(e.dataset.body); - var on = e.dataset.state !== '0'; - var mode = e.dataset.mode; - moduleObj.sendSocketNotification('SCREENLOGIC_HEATSTATE', {body: bodyId, state: on ? 0 : parseInt(mode)}); - e.classList.remove('control-on', 'control-off'); + let bodyId = parseInt(e.dataset.body); + let on = e.dataset.state !== '0'; + let mode = e.dataset.mode; + moduleObj.sendSocketNotification('SCREENLOGIC_HEATSTATE', {body: bodyId, state: on ? 0 : parseInt(mode)}); + e.classList.remove('control-on', 'control-off'); } function setHeatpoint(e, tempChange) { - var bodyId = parseInt(e.dataset.body); - var temp = parseInt(e.dataset.temperature) + tempChange; - moduleObj.sendSocketNotification('SCREENLOGIC_HEATPOINT', {body: bodyId, temperature: temp}); - e.classList.remove('control-on', 'control-off'); + let bodyId = parseInt(e.dataset.body); + let temp = parseInt(e.dataset.temperature) + tempChange; + moduleObj.sendSocketNotification('SCREENLOGIC_HEATPOINT', {body: bodyId, temperature: temp}); + e.classList.remove('control-on', 'control-off'); } diff --git a/README.md b/README.md index ed6eda2..4f6b304 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,16 @@ # MMM-ScreenLogic -A MagicMirror² module used to connect to a local Pentair ScreenLogic pool controller system. + +[MagicMirror²](https://github.com/MichMich/MagicMirror) module used to connect to a local Pentair ScreenLogic pool controller system. ## Installation + 1. Navigate into your MagicMirror's `modules` folder and execute `git clone https://github.com/parnic/MMM-ScreenLogic.git`. 2. `cd MMM-ScreenLogic` -3. Execute `npm install` to install the node dependencies. +3. Execute `npm install --production` to install the node dependencies. 4. Add the module inside `config.js` placing it where you prefer. ## Config + |Option|Type|Description|Default| |---|---|---|---| |`coldTemp`|Integer|Show the temperature colored blue if it's at or below this level for pool/spa (requires option `colored`). This is in whatever scale your system is set to (Fahrenheit/Celsius).|`84`| @@ -29,32 +32,36 @@ A MagicMirror² module use |`updateInterval`|Integer|How frequently, in milliseconds, to update pool data.|`30 * 60 * 1000` (every 30 minutes)| Here is an example of an entry in config.js -``` + +```js { - module: 'MMM-ScreenLogic', - header: 'Pool info', - position: 'top_left', - config: { - showSpaTemp: false, - columns: 2, - contentClass: 'thin', - showControls: true, - controls: [ - {type: 'circuit', id: 500}, - {type: 'circuit', id: 505, name: 'Pool'}, - {type: 'heatmode', body: 0, name: 'Pool heater'}, - {type: 'heatpoint', body: 0, name: 'Pool'}, - {type: 'heatmode', body: 1, heatMode: 2, name: 'Spa heater'}, - ] - } + module: 'MMM-ScreenLogic', + header: 'Pool info', + position: 'top_left', + config: { + showSpaTemp: false, + columns: 2, + contentClass: 'thin', + showControls: true, + controls: [ + {type: 'circuit', id: 500}, + {type: 'circuit', id: 505, name: 'Pool'}, + {type: 'heatmode', body: 0, name: 'Pool heater'}, + {type: 'heatpoint', body: 0, name: 'Pool'}, + {type: 'heatmode', body: 1, heatMode: 2, name: 'Spa heater'}, + ] + } }, ``` ## Screenshot -#### With color + +### With color + ![Screenshot with color](/screenshot.png?raw=true "colored: true") ## Notes + Pull requests are very welcome! If you'd like to see any additional functionality, don't hesitate to let me know. This module only works with ScreenLogic controllers on the local network via either a UDP broadcast on 255.255.255.255 or a direct connection if you've specified an address and port in the configuration. @@ -64,4 +71,5 @@ The data is updated every 30 minutes by default (configurable with `updateInterv When toggling a circuit or changing heat mode, sometimes other circuits are affected. For example, some pools share the same pump for the pool and spa, so when the pool is toggled on the spa must be toggled off. Unfortunately the ScreenLogic system doesn't update its internal status at any predictable rate, so the data on the screen can be wrong immediately after toggling a circuit until the next periodic update runs. If you know of a reliable way around this, please open a pull request! ## Libraries + This uses a Node.JS library I created for interfacing with ScreenLogic controllers over the network: [node-screenlogic](https://github.com/parnic/node-screenlogic), so feel free to check that out for more information. diff --git a/node_helper.js b/node_helper.js index cefd222..2b58e1c 100644 --- a/node_helper.js +++ b/node_helper.js @@ -1,210 +1,210 @@ var NodeHelper = require('node_helper'); module.exports = NodeHelper.create({ - start: function() { - this.setTimer(30 * 60 * 1000); - }, + start: function() { + this.setTimer(30 * 60 * 1000); + }, - doUpdate: function() { - var self = this; - getPoolData(this.config, function(poolData) { - self.sendSocketNotification('SCREENLOGIC_RESULT', poolData); - }); - }, + doUpdate: function() { + var self = this; + getPoolData(this.config, function(poolData) { + self.sendSocketNotification('SCREENLOGIC_RESULT', poolData); + }); + }, - setCircuit: function(circuitState) { - var self = this; - setCircuitState(circuitState, function(poolStatus) { - self.sendSocketNotification('SCREENLOGIC_CIRCUIT_DONE', {circuitState: circuitState, status: poolStatus}); - }); - }, + setCircuit: function(circuitState) { + var self = this; + setCircuitState(circuitState, function(poolStatus) { + self.sendSocketNotification('SCREENLOGIC_CIRCUIT_DONE', {circuitState: circuitState, status: poolStatus}); + }); + }, - setHeatpoint: function(heatpoint) { - var self = this; - setHeatpointState(heatpoint, function(poolStatus) { - self.sendSocketNotification('SCREENLOGIC_HEATPOINT_DONE', {heatpoint: heatpoint, status: poolStatus}); - }); - }, + setHeatpoint: function(heatpoint) { + var self = this; + setHeatpointState(heatpoint, function(poolStatus) { + self.sendSocketNotification('SCREENLOGIC_HEATPOINT_DONE', {heatpoint: heatpoint, status: poolStatus}); + }); + }, - setHeatstate: function(heatstate) { - var self = this; - setHeatstateState(heatstate, function(poolStatus) { - self.sendSocketNotification('SCREENLOGIC_HEATSTATE_DONE', {heatstate: heatstate, status: poolStatus}); - }); - }, + setHeatstate: function(heatstate) { + var self = this; + setHeatstateState(heatstate, function(poolStatus) { + self.sendSocketNotification('SCREENLOGIC_HEATSTATE_DONE', {heatstate: heatstate, status: poolStatus}); + }); + }, - setLightcmd: function(lightCmd) { - var self = this; - setLights(lightCmd, function(poolStatus) { - self.sendSocketNotification('SCREENLOGIC_LIGHTCMD_DONE', {lightCmd: lightCmd, status: poolStatus}); - }); - }, + setLightcmd: function(lightCmd) { + var self = this; + setLights(lightCmd, function(poolStatus) { + self.sendSocketNotification('SCREENLOGIC_LIGHTCMD_DONE', {lightCmd: lightCmd, status: poolStatus}); + }); + }, - restartTimer: function() { - var interval = this.updateInterval; - this.updateInterval = undefined; - this.setTimer(interval); - }, + restartTimer: function() { + var interval = this.updateInterval; + this.updateInterval = undefined; + this.setTimer(interval); + }, - setTimer: function(updateInterval) { - var update = true; - update = typeof this.updateInterval === 'undefined' || this.updateInterval != updateInterval; - this.updateInterval = updateInterval; + setTimer: function(updateInterval) { + var update = true; + update = typeof this.updateInterval === 'undefined' || this.updateInterval !== updateInterval; + this.updateInterval = updateInterval; - if (update) { - if (typeof this.timer !== 'undefined') { - clearInterval(this.timer); - } + if (update) { + if (typeof this.timer !== 'undefined') { + clearInterval(this.timer); + } - var self = this; - self.timer = setInterval(function() { - self.doUpdate() - }, self.updateInterval); - } - }, + var self = this; + self.timer = setInterval(function() { + self.doUpdate() + }, self.updateInterval); + } + }, - socketNotificationReceived: function(notification, payload) { - if (notification === 'SCREENLOGIC_CONFIG') { - this.config = payload; - this.setTimer(this.config.updateInterval); - } - if (notification === 'SCREENLOGIC_UPDATE') { - this.doUpdate(); - } - if (notification === 'SCREENLOGIC_CIRCUIT') { - this.setCircuit(payload); - } - if (notification === 'SCREENLOGIC_HEATPOINT') { - this.setHeatpoint(payload); - } - if (notification === 'SCREENLOGIC_HEATSTATE') { - this.setHeatstate(payload); - } - if (notification === 'SCREENLOGIC_LIGHTCMD') { - this.setLightcmd(payload); - } - } + socketNotificationReceived: function(notification, payload) { + if (notification === 'SCREENLOGIC_CONFIG') { + this.config = payload; + this.setTimer(this.config.updateInterval); + } + if (notification === 'SCREENLOGIC_UPDATE') { + this.doUpdate(); + } + if (notification === 'SCREENLOGIC_CIRCUIT') { + this.setCircuit(payload); + } + if (notification === 'SCREENLOGIC_HEATPOINT') { + this.setHeatpoint(payload); + } + if (notification === 'SCREENLOGIC_HEATSTATE') { + this.setHeatstate(payload); + } + if (notification === 'SCREENLOGIC_LIGHTCMD') { + this.setLightcmd(payload); + } + } }); const ScreenLogic = require('node-screenlogic'); var foundUnit; function getPoolData(config, cb) { - if (!foundUnit && typeof config !== 'undefined' && config.serverAddress && config.serverPort) { - foundUnit = new ScreenLogic.UnitConnection(config.serverPort, config.serverAddress); - } + if (!foundUnit && typeof config !== 'undefined' && config.serverAddress && config.serverPort) { + foundUnit = new ScreenLogic.UnitConnection(config.serverPort, config.serverAddress); + } - if (foundUnit) { - populateSystemData(cb); - } else { - findServer(cb); - } + if (foundUnit) { + populateSystemData(cb); + } else { + findServer(cb); + } } function findServer(cb) { - var finder = new ScreenLogic.FindUnits(); - finder.on('serverFound', function(server) { - finder.close(); + var finder = new ScreenLogic.FindUnits(); + finder.on('serverFound', function(server) { + finder.close(); - foundUnit = new ScreenLogic.UnitConnection(server); - populateSystemData(cb); - }); + foundUnit = new ScreenLogic.UnitConnection(server); + populateSystemData(cb); + }); - finder.search(); + finder.search(); } function populateSystemData(cb) { - var poolData = {}; + var poolData = {}; - if (!foundUnit) { - cb(poolData); - return; - } + if (!foundUnit) { + cb(poolData); + return; + } - foundUnit.once('loggedIn', function() { - foundUnit.getControllerConfig(); - }).once('controllerConfig', function(config) { - poolData.controllerConfig = config; - poolData.degStr = config.degC ? 'C' : 'F'; - foundUnit.getPoolStatus(); - }).once('poolStatus', function(status) { - poolData.status = status; + foundUnit.once('loggedIn', function() { + foundUnit.getControllerConfig(); + }).once('controllerConfig', function(config) { + poolData.controllerConfig = config; + poolData.degStr = config.degC ? 'C' : 'F'; + foundUnit.getPoolStatus(); + }).once('poolStatus', function(status) { + poolData.status = status; - foundUnit.close(); - cb(poolData); - }); + foundUnit.close(); + cb(poolData); + }); - foundUnit.connect(); + foundUnit.connect(); } function setCircuitState(circuitState, cb) { - if (!foundUnit) { - cb(); - return; - } + if (!foundUnit) { + cb(); + return; + } - foundUnit.once('loggedIn', function() { - foundUnit.setCircuitState(0, circuitState.id, circuitState.state); - }).once('circuitStateChanged', function() { - foundUnit.getPoolStatus(); - }).once('poolStatus', function(status) { - foundUnit.close(); - cb(status); - }); + foundUnit.once('loggedIn', function() { + foundUnit.setCircuitState(0, circuitState.id, circuitState.state); + }).once('circuitStateChanged', function() { + foundUnit.getPoolStatus(); + }).once('poolStatus', function(status) { + foundUnit.close(); + cb(status); + }); - foundUnit.connect(); + foundUnit.connect(); } function setHeatpointState(heatpoint, cb) { - if (!foundUnit) { - cb(); - return; - } + if (!foundUnit) { + cb(); + return; + } - foundUnit.once('loggedIn', function() { - foundUnit.setSetPoint(0, heatpoint.body, heatpoint.temperature); - }).once('setPointChanged', function() { - foundUnit.getPoolStatus(); - }).once('poolStatus', function(status) { - foundUnit.close(); - cb(status); - }); + foundUnit.once('loggedIn', function() { + foundUnit.setSetPoint(0, heatpoint.body, heatpoint.temperature); + }).once('setPointChanged', function() { + foundUnit.getPoolStatus(); + }).once('poolStatus', function(status) { + foundUnit.close(); + cb(status); + }); - foundUnit.connect(); + foundUnit.connect(); } function setHeatstateState(heatstate, cb) { - if (!foundUnit) { - cb(); - return; - } + if (!foundUnit) { + cb(); + return; + } - foundUnit.once('loggedIn', function() { - foundUnit.setHeatMode(0, heatstate.body, heatstate.state); - }).once('heatModeChanged', function() { - foundUnit.getPoolStatus(); - }).once('poolStatus', function(status) { - foundUnit.close(); - cb(status); - }); + foundUnit.once('loggedIn', function() { + foundUnit.setHeatMode(0, heatstate.body, heatstate.state); + }).once('heatModeChanged', function() { + foundUnit.getPoolStatus(); + }).once('poolStatus', function(status) { + foundUnit.close(); + cb(status); + }); - foundUnit.connect(); + foundUnit.connect(); } function setLights(lightCmd, cb) { - if (!foundUnit) { - cb(); - return; - } + if (!foundUnit) { + cb(); + return; + } - foundUnit.once('loggedIn', function() { - foundUnit.sendLightCommand(0, lightCmd); - }).once('sentLightCommand', function() { - foundUnit.getPoolStatus(); - }).once('poolStatus', function(status) { - foundUnit.close(); - cb(status); - }); + foundUnit.once('loggedIn', function() { + foundUnit.sendLightCommand(0, lightCmd); + }).once('sentLightCommand', function() { + foundUnit.getPoolStatus(); + }).once('poolStatus', function(status) { + foundUnit.close(); + cb(status); + }); - foundUnit.connect(); + foundUnit.connect(); } diff --git a/package-lock.json b/package-lock.json index bf71897..00e3317 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,628 @@ { "name": "magic-mirror-module-screenlogic", - "version": "1.0.3", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/code-frame": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", + "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.4" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", + "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", + "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.4", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, + "acorn": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.0.tgz", + "integrity": "sha512-+G7P8jJmCHr+S+cLfQxygbWhXy+8YTVGzAkpEbcLo2mLoL7tij/VG41QSHACSf5QgYRhMZYHuNc6drJaO0Da+w==", + "dev": true + }, + "acorn-jsx": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz", + "integrity": "sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==", + "dev": true + }, + "ajv": { + "version": "6.12.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", + "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", + "dev": true + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dev": true, + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint": { + "version": "7.7.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.7.0.tgz", + "integrity": "sha512-1KUxLzos0ZVsyL81PnRN335nDtQ8/vZUD6uMtWbF+5zDtjKcsklIi78XoE0MVL93QvWTu+E5y44VyyCsOMBrIg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.0.1", + "doctrine": "^3.0.0", + "enquirer": "^2.3.5", + "eslint-scope": "^5.1.0", + "eslint-utils": "^2.1.0", + "eslint-visitor-keys": "^1.3.0", + "espree": "^7.2.0", + "esquery": "^1.2.0", + "esutils": "^2.0.2", + "file-entry-cache": "^5.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^5.0.0", + "globals": "^12.1.0", + "ignore": "^4.0.6", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^3.13.1", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash": "^4.17.19", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "progress": "^2.0.0", + "regexpp": "^3.1.0", + "semver": "^7.2.1", + "strip-ansi": "^6.0.0", + "strip-json-comments": "^3.1.0", + "table": "^5.2.3", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + } + }, + "eslint-scope": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.0.tgz", + "integrity": "sha512-iiGRvtxWqgtx5m8EyQUJihBloE4EnYeGE/bz1wSPwJE6tZuJUtHlhqDM4Xj2ukE8Dyy1+HCZ4hE0fzIVMzb58w==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz", + "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^1.1.0" + } + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.2.0.tgz", + "integrity": "sha512-H+cQ3+3JYRMEIOl87e7QdHX70ocly5iW4+dttuR8iYSPr/hXKFb+7dBsZ7+u1adC4VrnPlTkv0+OwuPnDop19g==", + "dev": true, + "requires": { + "acorn": "^7.3.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.3.0" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.3.1.tgz", + "integrity": "sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "file-entry-cache": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz", + "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==", + "dev": true, + "requires": { + "flat-cache": "^2.0.1" + } + }, + "flat-cache": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz", + "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==", + "dev": true, + "requires": { + "flatted": "^2.0.0", + "rimraf": "2.6.3", + "write": "1.0.3" + } + }, + "flatted": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz", + "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globals": { + "version": "12.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz", + "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==", + "dev": true, + "requires": { + "type-fest": "^0.8.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", + "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "lodash": { + "version": "4.17.20", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz", + "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, "node-screenlogic": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/node-screenlogic/-/node-screenlogic-1.3.1.tgz", @@ -12,10 +631,261 @@ "smart-buffer": "~4.0.1" } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz", + "integrity": "sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==", + "dev": true, + "requires": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.3" + } + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "regexpp": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.1.0.tgz", + "integrity": "sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==", + "dev": true + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + } + }, "smart-buffer": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.0.2.tgz", "integrity": "sha512-JDhEpTKzXusOqXZ0BUIdH+CjFdO/CR3tLlf5CN34IypI+xMmXW1uB16OOY8z3cICbJlDAVJzNbwBhNO0wt9OAw==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "5.4.6", + "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz", + "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==", + "dev": true, + "requires": { + "ajv": "^6.10.2", + "lodash": "^4.17.14", + "slice-ansi": "^2.1.0", + "string-width": "^3.0.0" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "v8-compile-cache": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.1.1.tgz", + "integrity": "sha512-8OQ9CL+VWyt3JStj7HX7/ciTL2V3Rl1Wf5OL+SNTm0yK1KvtReVulksyeRnCANHHuUxHlQig+JJDlUhBt1NQDQ==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz", + "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } } } } diff --git a/package.json b/package.json index ddf798c..1fee369 100644 --- a/package.json +++ b/package.json @@ -8,5 +8,11 @@ "license": "MIT", "dependencies": { "node-screenlogic": "1.x" + }, + "devDependencies": { + "eslint": "^7.7.0" + }, + "scripts": { + "lint": "./node_modules/.bin/eslint ." } } diff --git a/screenlogic.css b/screenlogic.css index c86daf9..3eccd08 100644 --- a/screenlogic.css +++ b/screenlogic.css @@ -1,13 +1,13 @@ .MMM-ScreenLogic table.colored .cold-temp { - color: #BCDDFF; + color: #BCDDFF; } .MMM-ScreenLogic table.colored .hot-temp { - color: #FF8E99; + color: #FF8E99; } .MMM-ScreenLogic td { - width: 33%; + width: 33%; } .MMM-ScreenLogic .control { @@ -19,11 +19,11 @@ text-align: center; line-height: 1.5; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; - box-sizing: border-box; - position: relative; - width: 80%; - height: 5rem; - margin: auto; + box-sizing: border-box; + position: relative; + width: 80%; + height: 5rem; + margin: auto; font-weight: bold; -webkit-user-select: none; -moz-user-select: none; @@ -34,13 +34,13 @@ } .MMM-ScreenLogic .control:after { - padding-bottom: 100%; - content: ""; - display: block; + padding-bottom: 100%; + content: ""; + display: block; } .MMM-ScreenLogic .content { - position: absolute; + position: absolute; width: 90%; height: 90%; left: 0px; @@ -52,13 +52,13 @@ } .MMM-ScreenLogic .control-on { - background: #28a745 !important; - border-color: #28a745 !important; + background: #28a745 !important; + border-color: #28a745 !important; } .MMM-ScreenLogic .control-off { - background: transparent !important; - border-color: #6c757d !important; + background: transparent !important; + border-color: #6c757d !important; } .MMM-ScreenLogic .temperature-container { @@ -81,10 +81,10 @@ background: #000; border: 0px solid #6c757d; color: #fff; - position: relative; - width: 80%; - height: 2.45rem; - margin: auto; + position: relative; + width: 80%; + height: 2.45rem; + margin: auto; font-weight: bold; -webkit-user-select: none; -moz-user-select: none;