diff --git a/.all-contributorsrc b/.all-contributorsrc
index 6478e026..133c511c 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -85,6 +85,17 @@
"contributions": [
"translation"
]
+ },
+ {
+ "login": "bugsounet",
+ "name": "Bugsounet - Cédric",
+ "avatar_url": "https://avatars.githubusercontent.com/u/30669209?v=4",
+ "profile": "http://www.bugsounet.fr",
+ "contributions": [
+ "code",
+ "bug",
+ "review"
+ ]
}
],
"contributorsPerLine": 7,
diff --git a/.env.template b/.env.template
deleted file mode 100644
index 532744e4..00000000
--- a/.env.template
+++ /dev/null
@@ -1,3 +0,0 @@
-CLIENT_ID=""
-CLIENT_SECRET=""
-REFRESH_TOKEN=""
diff --git a/.github/renovate.json b/.github/renovate.json
index 64ae4308..cfea8199 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -2,7 +2,7 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"config:base",
- "schedule:automergeMonthly",
+ "schedule:automergeMonthly"
],
"packageRules": [
{
diff --git a/.github/workflows/validation.yml b/.github/workflows/validation.yml
index 96a79e55..c2d27925 100644
--- a/.github/workflows/validation.yml
+++ b/.github/workflows/validation.yml
@@ -51,25 +51,6 @@ jobs:
run: npm clean-install
- name: Validate CSS Sources
run: npm run validate:css
- unit:
- runs-on: ubuntu-latest
- name: 'Unit Tests'
- steps:
- - name: Checkout Code
- uses: actions/checkout@v4
- - name: Use Node.js ${{ env.node-version }}
- uses: actions/setup-node@v4
- with:
- node-version: ${{ env.node-version }}
- cache: "npm"
- - name: Install Dependencies
- run: npm clean-install
- - name: Execute Unit Tests
- run: npm run test
- env:
- CLIENT_ID: ${{ secrets.CLIENT_ID }}
- CLIENT_SECRET: ${{ secrets.CLIENT_SECRET }}
- REFRESH_TOKEN: ${{ secrets.REFRESH_TOKEN }}
package-lock-is-up-to-date:
runs-on: ubuntu-latest
steps:
diff --git a/.gitignore b/.gitignore
index 23ccfcc4..259ded2a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ node_modules
report
.env*
.DS_Store
+/token.json
diff --git a/README.md b/README.md
index 085e10b1..925e13f7 100644
--- a/README.md
+++ b/README.md
@@ -29,11 +29,7 @@ cd ~/MagicMirror/modules && git clone https://github.com/CFenner/MMM-Netatmo net
:warning: Note that the checkout folder is named `netatmo` and not `MMM-Netatmo` as the repository.
-Navigate into the module folder and install missing dependencies:
-
-```shell
-cd netatmo && npm ci --production --ignore-scripts
-```
+Since v2.1.0: **No special dependencies and no others commands are now needed!**
### Connection to Netatmo Service API
@@ -110,6 +106,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
Otto Lote 💻 |
cgillinger 🌍 |
+ Bugsounet - Cédric 💻 🐛 👀 |
diff --git a/helper.js b/helper.js
index 95155370..b5dd4722 100644
--- a/helper.js
+++ b/helper.js
@@ -2,11 +2,12 @@
* Module: MMM-Netatmo
*
* By Christopher Fenner https://github.com/CFenner
+ * Review @bugsounet https://github.com/bugsounet
* MIT Licensed.
*/
const fs = require('fs')
const path = require('path')
-const URLSearchParams = require('@ungap/url-search-params')
+const moment = require('moment')
module.exports = {
notifications: {
@@ -15,117 +16,235 @@ module.exports = {
DATA: 'NETATMO_DATA',
DATA_RESPONSE: 'NETATMO_DATA_RESPONSE',
},
- start: function () {
+
+ start () {
console.log('Netatmo helper started ...')
this.token = null
},
- authenticate: async function (config) {
- const self = this
- self.config = config
+ async authenticate () {
const params = new URLSearchParams()
params.append('grant_type', 'refresh_token')
- params.append('refresh_token', self.refresh_token || self.config.refresh_token)
- params.append('client_id', self.config.clientId)
- params.append('client_secret', self.config.clientSecret)
+ params.append('refresh_token', this.refreshToken)
+ params.append('client_id', this.clientId)
+ params.append('client_secret', this.clientSecret)
try {
- const result = await fetch('https://' + self.config.apiBase + self.config.authEndpoint, {
+ const result = await fetch(`https://${this.config.apiBase}${this.config.authEndpoint}`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: params,
- }).then(response => response.json())
+ }).then((response) => response.json())
if (result.error) {
- throw new Error(result.error + ': ' + result.error_description)
- }
+ throw new Error(`${result.error} : ${result.error_description}`)
+ };
+
+ this.token = result.access_token
+ this.token_expires_in = result.expires_in
+ this.refreshToken = result.refresh_token
+ console.log('Netatmo: Authenticated')
+
+ // write in token file and provides for token refresh
+ this.writeToken(result)
+ if (result.expires_in) {
+ const expireAt = moment(Date.now() + (result.expires_in * 1000)).format('LLLL')
+ console.log(`Netatmo: New Token Expire ${expireAt}`)
+ setTimeout(() => this.authenticateRefresh(result.refresh_token), (result.expires_in - 60) * 1000)
+ };
- console.log('UPDATING TOKEN ' + result.access_token)
- self.token = result.access_token
- self.token_expires_in = result.expires_in
- self.refresh_token = result.refresh_token
- // we got a new token, save it to main file to allow it to request the datas
- self.sendSocketNotification(self.notifications.AUTH_RESPONSE, {
+ // inform module AUTH ok
+ this.sendSocketNotification(this.notifications.AUTH_RESPONSE, {
status: 'OK',
})
} catch (error) {
- console.log('error:', error)
- self.sendSocketNotification(self.notifications.AUTH_RESPONSE, {
+ console.error('Netatmo:', error)
+ this.sendSocketNotification(this.notifications.AUTH_RESPONSE, {
payloadReturn: error,
status: 'NOTOK',
message: error,
})
- }
+ };
},
- loadData: async function (config) {
- const self = this
- self.config = config
- if (self.config.mockData === true) {
- self.sendSocketNotification(self.notifications.DATA_RESPONSE, {
+ async loadData () {
+ if (this.config.mockData === true) {
+ this.sendSocketNotification(this.notifications.DATA_RESPONSE, {
payloadReturn: this.mockData(),
status: 'OK',
})
return
- }
- if (self.token === null || self.token === undefined) {
- self.sendSocketNotification(self.notifications.DATA_RESPONSE, {
+ };
+
+ if (!this.token) {
+ this.sendSocketNotification(this.notifications.DATA_RESPONSE, {
payloadReturn: 400,
status: 'INVALID_TOKEN',
message: 'token not set',
})
return
- }
+ };
try {
- let result = await fetch('https://' + self.config.apiBase + self.config.dataEndpoint, {
+ let result = await fetch(`https://${this.config.apiBase}${this.config.dataEndpoint}`, {
headers: {
'Content-Type': 'application/json',
- Authorization: `Bearer ${self.token}`,
+ Authorization: `Bearer ${this.token}`,
},
})
if (result.status === 403) {
- console.log('status code:', result.status, '\n', result.statusText)
- self.sendSocketNotification(self.notifications.DATA_RESPONSE, {
+ console.warn(`Netatmo: status code: ${result.status} (${result.statusText})`)
+ this.sendSocketNotification(this.notifications.DATA_RESPONSE, {
payloadReturn: result.statusText,
status: 'INVALID_TOKEN',
message: result,
})
return
- }
+ };
result = await result.json()
if (result.error) {
throw new Error(result.error.message)
- }
+ };
- self.sendSocketNotification(self.notifications.DATA_RESPONSE, {
+ this.sendSocketNotification(this.notifications.DATA_RESPONSE, {
payloadReturn: result.body.devices,
status: 'OK',
})
} catch (error) {
- console.log('error:', error)
- self.sendSocketNotification(self.notifications.DATA_RESPONSE, {
+ console.error('Netatmo:', error)
+ this.sendSocketNotification(this.notifications.DATA_RESPONSE, {
payloadReturn: error,
status: 'NOTOK',
message: error,
})
- }
+ };
},
- mockData: function () {
+
+ mockData () {
const sample = fs.readFileSync(path.join(__dirname, 'sample', 'sample.json'), 'utf8')
return JSON.parse(sample)
},
- socketNotificationReceived: function (notification, payload) {
+
+ socketNotificationReceived (notification, payload) {
switch (notification) {
+ case 'INIT':
+ this.Init(payload)
+ break
case this.notifications.AUTH:
- this.authenticate(payload)
+ this.authenticate()
break
case this.notifications.DATA:
- this.loadData(payload)
+ this.loadData()
break
}
},
+
+ Init (config) {
+ this.config = config
+ if (!this.config.clientId) {
+ console.error('Netatmo: clientId not set in config.')
+ return
+ }
+ this.clientId = this.config.clientId
+
+ if (!this.config.clientSecret) {
+ console.error('Netatmo: clientSecret not set in config.')
+ return
+ }
+ this.clientSecret = this.config.clientSecret
+
+ const refreshToken = this.readToken()
+ this.refreshToken = refreshToken || this.config.refresh_token
+
+ if (!this.refreshToken) {
+ console.error('Netatmo: refresh_token not set in config.')
+ return
+ }
+
+ console.log('Netatmo: Initialized')
+ this.authenticate()
+ },
+
+ /* from MMM-NetatmoThermostat
+ * @bugsounet
+ */
+ readToken () {
+ const file = path.resolve(__dirname, './token.json')
+ // check presence of token.json
+ if (fs.existsSync(file)) {
+ console.log('Netatmo: using token.json file')
+ const tokenFile = JSON.parse(fs.readFileSync(file))
+ const refreshToken = tokenFile.refresh_token
+ if (!refreshToken) {
+ console.error('Netatmo: Token not found in token.json file')
+ console.log('Netatmo: using refresh_token from config')
+ return null
+ }
+ return refreshToken
+ }
+ // Token file not used
+ console.log('Netatmo: using refresh_token from config')
+ return null
+ },
+
+ writeToken (token) {
+ try {
+ const file = path.resolve(__dirname, './token.json')
+ fs.writeFileSync(file, JSON.stringify(token))
+ console.log('Netatmo: token.json was written successfully')
+ return token
+ } catch (error) {
+ ;
+ console.error('Netatmo: writeToken error', error.message)
+ return null
+ };
+ },
+
+ // Refresh Token
+ async authenticateRefresh (refreshToken) {
+ console.log('Netatmo: Refresh Token')
+ const params = new URLSearchParams()
+ params.append('grant_type', 'refresh_token')
+ params.append('refresh_token', refreshToken)
+ params.append('client_id', this.clientId)
+ params.append('client_secret', this.clientSecret)
+
+ try {
+ const result = await fetch(`https://${this.config.apiBase}${this.config.authEndpoint}`, {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
+ body: params,
+ }).then((response) => response.json())
+
+ if (result.error) {
+ throw new Error(result.error)
+ };
+
+ this.writeToken(result)
+ this.token = result.access_token
+ console.log('Netatmo: TOKEN Updated')
+
+ if (result.expires_in) {
+ const expireAt = moment(Date.now() + (result.expires_in * 1000)).format('LLLL')
+ console.log(`Netatmo: New Token Expire ${expireAt}`)
+ setTimeout(() => this.authenticateRefresh(result.refresh_token), (result.expires_in - 60) * 1000)
+ };
+
+ this.sendSocketNotification(this.notifications.AUTH_RESPONSE, {
+ status: 'OK',
+ })
+ } catch (error) {
+ console.error('Netatmo:', error)
+ this.sendSocketNotification(this.notifications.AUTH_RESPONSE, {
+ payloadReturn: error,
+ status: 'NOTOK',
+ message: error,
+ })
+ console.log('Netatmo: Retry login in 60 sec')
+ setTimeout(() => this.authenticate(this.config), 60 * 1000)
+ }
+ },
}
diff --git a/helper.test.js b/helper.test.js
deleted file mode 100644
index c0d65377..00000000
--- a/helper.test.js
+++ /dev/null
@@ -1,151 +0,0 @@
-require('dotenv').config()
-const moduleUnderTest = require('./helper.js')
-
-const apiBase = 'api.netatmo.com'
-const authEndpoint = '/oauth2/token'
-const dataEndpoint = '/api/getstationsdata'
-
-describe('helper', () => {
- afterEach(() => {
- delete moduleUnderTest.token
- delete moduleUnderTest.token_expires_in
- delete moduleUnderTest.refresh_token
- delete moduleUnderTest.sendSocketNotification
- })
- describe('data', () => {
- test('existing token', async () => {
- // prepare
- expect(moduleUnderTest).not.toHaveProperty('token')
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {})
- await moduleUnderTest.authenticate({
- apiBase,
- authEndpoint,
- refresh_token: process.env.REFRESH_TOKEN,
- clientId: process.env.CLIENT_ID,
- clientSecret: process.env.CLIENT_SECRET,
- })
- expect(moduleUnderTest).toHaveProperty('token')
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.DATA_RESPONSE)
- expect(payload).toHaveProperty('status', 'OK')
- expect(payload).toHaveProperty('payloadReturn')
- expect(payload.payloadReturn).toHaveLength(2)
- })
- expect(moduleUnderTest).toHaveProperty('token')
- // test
- await moduleUnderTest.loadData({
- apiBase,
- dataEndpoint,
- })
- // assert
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
-
- test('with missing token', async () => {
- // moduleUnderTest.token = process.env.TOKEN
- // prepare
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.DATA_RESPONSE)
- expect(payload).toHaveProperty('status', 'INVALID_TOKEN')
- })
- // test
- await moduleUnderTest.loadData({
- apiBase,
- dataEndpoint,
- })
- // assert
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
-
- test('with invalid token', async () => {
- moduleUnderTest.token = 'something'
- // prepare
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.DATA_RESPONSE)
- expect(payload).toHaveProperty('status', 'INVALID_TOKEN')
- })
- // test
- await moduleUnderTest.loadData({
- apiBase,
- dataEndpoint,
- })
- // assert
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
- })
-
- describe('authentication', () => {
- test('with refresh_token from config', async () => {
- // prepare
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.AUTH_RESPONSE)
- expect(payload).toHaveProperty('status', 'OK')
- })
- expect(moduleUnderTest).not.toHaveProperty('token')
- expect(moduleUnderTest).not.toHaveProperty('token_expires_in')
- expect(moduleUnderTest).not.toHaveProperty('refresh_token')
- // test
- await moduleUnderTest.authenticate({
- apiBase,
- authEndpoint,
- refresh_token: process.env.REFRESH_TOKEN,
- clientId: process.env.CLIENT_ID,
- clientSecret: process.env.CLIENT_SECRET,
- })
- // assert
- expect(moduleUnderTest).toHaveProperty('token')
- expect(moduleUnderTest).toHaveProperty('token_expires_in')
- expect(moduleUnderTest).toHaveProperty('refresh_token')
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
-
- test('with refresh_token from object', async () => {
- // prepare
- moduleUnderTest.refresh_token = process.env.REFRESH_TOKEN
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.AUTH_RESPONSE)
- expect(payload).toHaveProperty('status', 'OK')
- })
- expect(moduleUnderTest).not.toHaveProperty('token')
- expect(moduleUnderTest).not.toHaveProperty('token_expires_in')
- expect(moduleUnderTest).toHaveProperty('refresh_token')
- // test
- await moduleUnderTest.authenticate({
- apiBase,
- authEndpoint,
- refresh_token: '',
- clientId: process.env.CLIENT_ID,
- clientSecret: process.env.CLIENT_SECRET,
- })
- // assert
- expect(moduleUnderTest).toHaveProperty('token')
- expect(moduleUnderTest).toHaveProperty('token_expires_in')
- expect(moduleUnderTest).toHaveProperty('refresh_token')
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
-
- test('without refresh_token', async () => {
- // prepare
- moduleUnderTest.sendSocketNotification = jest.fn((type, payload) => {
- expect(type).toBe(moduleUnderTest.notifications.AUTH_RESPONSE)
- expect(payload).toHaveProperty('status', 'NOTOK')
- })
- expect(moduleUnderTest).not.toHaveProperty('token')
- expect(moduleUnderTest).not.toHaveProperty('token_expires_in')
- expect(moduleUnderTest).not.toHaveProperty('refresh_token')
- // test
- await moduleUnderTest.authenticate({
- apiBase,
- authEndpoint,
- refresh_token: '',
- clientId: process.env.CLIENT_ID,
- clientSecret: process.env.CLIENT_SECRET,
- })
- // assert
- expect(moduleUnderTest).not.toHaveProperty('token')
- expect(moduleUnderTest).not.toHaveProperty('token_expires_in')
- expect(moduleUnderTest).not.toHaveProperty('refresh_token')
- expect(moduleUnderTest.sendSocketNotification).toHaveBeenCalled()
- })
- })
-})
diff --git a/netatmo.js b/netatmo.js
index 8e336011..d8bf2898 100755
--- a/netatmo.js
+++ b/netatmo.js
@@ -64,24 +64,23 @@ Module.register('netatmo', {
RAIN_PER_DAY: 'sum_rain_24',
},
// init method
- start: function () {
- const self = this
+ start () {
Log.info(`Starting module: ${this.name}`)
- self.loaded = false
- self.moduleList = []
+ this.loaded = false
+ this.moduleList = []
- // get a new token at start-up. When receive, GET_CAMERA_EVENTS will be requested
- setTimeout(function () {
- self.sendSocketNotification(self.notifications.DATA, self.config)
+ // get a new token at start-up.
+ setTimeout(() => {
+ // best way is using initialize at start and if auth OK --> fetch data
+ this.sendSocketNotification('INIT', this.config)
}, this.config.initialDelay * 1000)
// set auto-update
- setInterval(function () {
- // request directly the data, with the previous token. When the token will become invalid (error 403), it will be requested again
- self.sendSocketNotification(self.notifications.DATA, self.config)
+ setInterval(() => {
+ this.sendSocketNotification(this.notifications.DATA)
}, this.config.updateInterval * 60 * 1000 + this.config.initialDelay * 1000)
},
- updateModuleList: function (stationList) {
+ updateModuleList (stationList) {
let moduleList = []
for (const station of stationList) {
@@ -111,7 +110,7 @@ Module.register('netatmo', {
}
this.moduleList = moduleList
},
- getModule: function (module, stationName) {
+ getModule (module, stationName) {
const result = {}
result.name = module.module_name
@@ -132,7 +131,7 @@ Module.register('netatmo', {
name: measurement,
value: this.getValue(measurement, 0),
unit: this.getUnit(measurement),
- icon: this.getIcon(measurement, 0) + ' flash red',
+ icon: `${this.getIcon(measurement, 0)} flash red`,
label: this.translate(measurement.toUpperCase()),
})
@@ -245,11 +244,13 @@ Module.register('netatmo', {
}
return result
},
- getMeasurement: function (module, measurement, value) {
+ getMeasurement (module, measurement, value) {
+ /* eslint-disable no-param-reassign */
value = value || module.dashboard_data[measurement]
if (measurement === this.measurement.TEMPERATURE_TREND || measurement === this.measurement.PRESSURE_TREND) {
value = value || 'undefined'
}
+ /* eslint-enable no-param-reassign */
return {
name: measurement,
value: this.getValue(measurement, value),
@@ -258,12 +259,12 @@ Module.register('netatmo', {
label: this.translate(measurement.toUpperCase()),
}
},
- kebabCase: function (name) {
+ kebabCase (name) {
return name.replace(/([a-z])([A-Z])/g, '$1-$2')
.replace(/[\s_]+/g, '-')
.toLowerCase()
},
- getValue: function (measurement, value) {
+ getValue (measurement, value) {
if (!value) { return value }
switch (measurement) {
case this.measurement.CO2:
@@ -288,7 +289,7 @@ Module.register('netatmo', {
return value.toFixed(0)// + ' km/h'
case this.measurement.WIND_ANGLE:
case this.measurement.GUST_ANGLE:
- return this.getDirection(value) + ' | ' + value// + '°'
+ return `${this.getDirection(value)} | ${value}`// + '°'
case this.measurement.TEMPERATURE_TREND:
case this.measurement.PRESSURE_TREND:
return this.translate(value.toUpperCase())
@@ -296,7 +297,7 @@ Module.register('netatmo', {
return value
}
},
- getUnit: function (measurement) {
+ getUnit (measurement) {
switch (measurement) {
case this.measurement.CO2:
return 'ppm'
@@ -325,7 +326,7 @@ Module.register('netatmo', {
return ''
}
},
- getDirection: function (value) {
+ getDirection (value) {
if (value < 11.25) return 'N'
if (value < 33.75) return 'NNE'
if (value < 56.25) return 'NE'
@@ -344,13 +345,13 @@ Module.register('netatmo', {
if (value < 348.75) return 'NNW'
return 'N'
},
- getCO2Status: function (value) {
+ getCO2Status (value) {
if (!value || value === 'undefined' || value < 0) return 'undefined'
if (value >= this.config.thresholdCO2Bad) return 'bad'
if (value >= this.config.thresholdCO2Average) return 'average'
return 'good'
},
- getIcon: function (dataType, value) {
+ getIcon (dataType, value) {
switch (dataType) {
// case this.measurement.CO2:
// return 'fa-lungs'
@@ -378,26 +379,26 @@ Module.register('netatmo', {
return ''
}
},
- getTrendIcon: function (value) {
+ getTrendIcon (value) {
if (value === 'stable') return 'fa-chevron-circle-right'
if (value === 'down') return 'fa-chevron-circle-down'
if (value === 'up') return 'fa-chevron-circle-up'
if (value === 'undefined') return 'fa-times-circle'
},
- getBatteryIcon: function (value) {
+ getBatteryIcon (value) {
if (value > 80) return 'fa-battery-full'
if (value > 60) return 'fa-battery-three-quarters'
if (value > 40) return 'fa-battery-half'
if (value > 20) return 'fa-battery-quarter'
return 'fa-battery-empty flash red'
},
- getStyles: function () {
+ getStyles () {
return [`${this.name}.${this.config.design}.css`]
},
- getTemplate: function () {
+ getTemplate () {
return `${this.name}.${this.config.design}.njk`
},
- getTemplateData: function () {
+ getTemplateData () {
return {
loaded: this.loaded,
showLastMessage: this.config.showLastMessage,
@@ -417,7 +418,7 @@ Module.register('netatmo', {
labelLoading: this.translate('LOADING'),
}
},
- getTranslations: function () {
+ getTranslations () {
return {
en: 'l10n/en.json', // fallback language
cs: 'l10n/cs.json',
@@ -430,29 +431,31 @@ Module.register('netatmo', {
sv: 'l10n/sv.json',
}
},
- socketNotificationReceived: function (notification, payload) {
- const self = this
- Log.debug('received ' + notification)
+ socketNotificationReceived (notification, payload) {
+ Log.debug(`Netatmo: received ${notification}`)
switch (notification) {
- case self.notifications.AUTH_RESPONSE:
+ case this.notifications.AUTH_RESPONSE:
if (payload.status === 'OK') {
- self.sendSocketNotification(self.notifications.DATA, self.config)
+ console.log('Netatmo: AUTH OK')
+ this.sendSocketNotification(this.notifications.DATA)
} else {
- console.log('AUTH FAILED ' + payload.message)
+ console.error(`Netatmo: AUTH FAILED ${payload.message}`)
}
break
- case self.notifications.DATA_RESPONSE:
+ case this.notifications.DATA_RESPONSE:
if (payload.status === 'OK') {
console.log('Devices %o', payload.payloadReturn)
const stationList = payload.payloadReturn
- self.updateModuleList(stationList)
- self.updateDom(self.config.animationSpeed)
+ this.updateModuleList(stationList)
+ this.updateDom(this.config.animationSpeed)
} else if (payload.status === 'INVALID_TOKEN') {
// node_module has no valid token, reauthenticate
- console.log('DATA FAILED, refreshing token')
- self.sendSocketNotification(self.notifications.AUTH, self.config)
+ console.error('DATA FAILED, refreshing token')
+ // i'm not agree with this... can have error 403 loop
+ // --> managed with node_helper
+ // this.sendSocketNotification(this.notifications.AUTH)
} else {
- console.log('DATA FAILED ' + payload.message)
+ console.error(`Netatmo: DATA FAILED ${payload.message}`)
}
break
}
diff --git a/node_helper.js b/node_helper.js
index 3b9899da..3b9b38ac 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -5,6 +5,6 @@
* MIT Licensed.
*/
const NodeHelper = require('node_helper')
-const helper = require('./helper')
+const helper = require('./helper.js')
module.exports = NodeHelper.create(helper)
diff --git a/package-lock.json b/package-lock.json
index df0459de..fa861ad6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,30 +1,27 @@
{
"name": "netatmo",
- "version": "2.0.0",
+ "version": "2.1.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "netatmo",
- "version": "2.0.0",
+ "version": "2.1.0",
"license": "MIT",
- "dependencies": {
- "@ungap/url-search-params": "0.2.2"
- },
"devDependencies": {
- "@snyk/protect": "1.1291.0",
+ "@snyk/protect": "1.1291.1",
"dotenv": "16.3.1",
"eslint": "8.57.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-n": "16.6.2",
- "eslint-plugin-promise": "6.1.1",
+ "eslint-plugin-promise": "6.2.0",
"jest": "29.7.0",
"jsonlint-newline-fork": "1.6.8",
"less": "4.2.0",
"markdownlint": "0.32.1",
- "stylelint": "16.5.0",
- "stylelint-config-standard": "36.0.0"
+ "stylelint": "16.6.1",
+ "stylelint-config-standard": "36.0.1"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@@ -681,9 +678,9 @@
"dev": true
},
"node_modules/@csstools/css-parser-algorithms": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz",
- "integrity": "sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA==",
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.3.tgz",
+ "integrity": "sha512-xI/tL2zxzEbESvnSxwFgwvy5HS00oCXxL4MLs6HUiDcYfwowsoQaABKxUElp1ARITrINzBnsECOc1q0eg2GOrA==",
"dev": true,
"funding": [
{
@@ -695,17 +692,18 @@
"url": "https://opencollective.com/csstools"
}
],
+ "license": "MIT",
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
- "@csstools/css-tokenizer": "^2.2.4"
+ "@csstools/css-tokenizer": "^2.3.1"
}
},
"node_modules/@csstools/css-tokenizer": {
- "version": "2.2.4",
- "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz",
- "integrity": "sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw==",
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.3.1.tgz",
+ "integrity": "sha512-iMNHTyxLbBlWIfGtabT157LH9DUx9X8+Y3oymFEuMj8HNc+rpE3dPFGFgHjpKfjeFDjLjYIAIhXPGvS2lKxL9g==",
"dev": true,
"funding": [
{
@@ -717,14 +715,15 @@
"url": "https://opencollective.com/csstools"
}
],
+ "license": "MIT",
"engines": {
"node": "^14 || ^16 || >=18"
}
},
"node_modules/@csstools/media-query-list-parser": {
- "version": "2.1.9",
- "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz",
- "integrity": "sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA==",
+ "version": "2.1.11",
+ "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.11.tgz",
+ "integrity": "sha512-uox5MVhvNHqitPP+SynrB1o8oPxPMt2JLgp5ghJOWf54WGQ5OKu47efne49r1SWqs3wRP8xSWjnO9MBKxhB1dA==",
"dev": true,
"funding": [
{
@@ -736,18 +735,19 @@
"url": "https://opencollective.com/csstools"
}
],
+ "license": "MIT",
"engines": {
"node": "^14 || ^16 || >=18"
},
"peerDependencies": {
- "@csstools/css-parser-algorithms": "^2.6.1",
- "@csstools/css-tokenizer": "^2.2.4"
+ "@csstools/css-parser-algorithms": "^2.6.3",
+ "@csstools/css-tokenizer": "^2.3.1"
}
},
"node_modules/@csstools/selector-specificity": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz",
- "integrity": "sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz",
+ "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==",
"dev": true,
"funding": [
{
@@ -759,6 +759,7 @@
"url": "https://opencollective.com/csstools"
}
],
+ "license": "MIT-0",
"engines": {
"node": "^14 || ^16 || >=18"
},
@@ -767,10 +768,11 @@
}
},
"node_modules/@dual-bundle/import-meta-resolve": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz",
- "integrity": "sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz",
+ "integrity": "sha512-+nxncfwHM5SgAtrVzgpzJOI1ol0PkumhVo469KCf9lUi21IGcY90G98VuHm9VRrUypmAzawAHO9bs6hqeADaVg==",
"dev": true,
+ "license": "MIT",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
@@ -1346,10 +1348,11 @@
}
},
"node_modules/@snyk/protect": {
- "version": "1.1291.0",
- "resolved": "https://registry.npmjs.org/@snyk/protect/-/protect-1.1291.0.tgz",
- "integrity": "sha512-BRbgzSOSlzIBmhdEqM0y0q8uhYd2h+tfl3OuMH62JvQ+AI9lFV5Va99gl+wqS8GBBOohQmIh4HnuD25LMCdO7Q==",
+ "version": "1.1291.1",
+ "resolved": "https://registry.npmjs.org/@snyk/protect/-/protect-1.1291.1.tgz",
+ "integrity": "sha512-Xb9Q4KkZTGOm5BGDBQDnPOU8YmIDUmj9Ub6O1qsCfkGm8Jk+VU6pTl5nhDYS/zmA8n5xJYEYRKUVI9mUZG8Hbg==",
"dev": true,
+ "license": "Apache-2.0",
"bin": {
"snyk-protect": "bin/snyk-protect"
},
@@ -1473,11 +1476,6 @@
"integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==",
"dev": true
},
- "node_modules/@ungap/url-search-params": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@ungap/url-search-params/-/url-search-params-0.2.2.tgz",
- "integrity": "sha512-qQsguKXZVKdCixOHX9jqnX/K/1HekPDpGKyEcXHT+zR6EjGA7S4boSuelL4uuPv6YfhN0n8c4UxW+v/Z3gM2iw=="
- },
"node_modules/acorn": {
"version": "8.11.2",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.2.tgz",
@@ -1847,12 +1845,13 @@
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
@@ -2818,15 +2817,19 @@
"dev": true
},
"node_modules/eslint-plugin-promise": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.1.1.tgz",
- "integrity": "sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.2.0.tgz",
+ "integrity": "sha512-QmAqwizauvnKOlifxyDj2ObfULpHQawlg/zQdgEixur9vl0CvZGv/LCJV2rtj3210QCoeGBzVMfMXqGAOr/4fA==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
"peerDependencies": {
- "eslint": "^7.0.0 || ^8.0.0"
+ "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0"
}
},
"node_modules/eslint-scope": {
@@ -3109,10 +3112,11 @@
}
},
"node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -3148,10 +3152,11 @@
}
},
"node_modules/flatted": {
- "version": "3.2.9",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz",
- "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==",
- "dev": true
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/for-each": {
"version": "0.3.3",
@@ -3831,6 +3836,7 @@
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
@@ -4789,10 +4795,11 @@
}
},
"node_modules/known-css-properties": {
- "version": "0.30.0",
- "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.30.0.tgz",
- "integrity": "sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==",
- "dev": true
+ "version": "0.31.0",
+ "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.31.0.tgz",
+ "integrity": "sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/less": {
"version": "4.2.0",
@@ -5062,12 +5069,13 @@
}
},
"node_modules/micromatch": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
- "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
+ "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "braces": "^3.0.2",
+ "braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
@@ -5453,10 +5461,11 @@
}
},
"node_modules/picocolors": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz",
+ "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/picomatch": {
"version": "2.3.1",
@@ -5562,10 +5571,11 @@
}
},
"node_modules/postcss-selector-parser": {
- "version": "6.0.16",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz",
- "integrity": "sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz",
+ "integrity": "sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -6161,16 +6171,27 @@
}
},
"node_modules/stylelint": {
- "version": "16.5.0",
- "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.5.0.tgz",
- "integrity": "sha512-IlCBtVrG+qTy3v+tZTk50W8BIomjY/RUuzdrDqdnlCYwVuzXtPbiGfxYqtyYAyOMcb+195zRsuHn6tgfPmFfbw==",
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-16.6.1.tgz",
+ "integrity": "sha512-yNgz2PqWLkhH2hw6X9AweV9YvoafbAD5ZsFdKN9BvSDVwGvPh+AUIrn7lYwy1S7IHmtFin75LLfX1m0D2tHu8Q==",
"dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/stylelint"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "@csstools/css-parser-algorithms": "^2.6.1",
- "@csstools/css-tokenizer": "^2.2.4",
- "@csstools/media-query-list-parser": "^2.1.9",
- "@csstools/selector-specificity": "^3.0.3",
- "@dual-bundle/import-meta-resolve": "^4.0.0",
+ "@csstools/css-parser-algorithms": "^2.6.3",
+ "@csstools/css-tokenizer": "^2.3.1",
+ "@csstools/media-query-list-parser": "^2.1.11",
+ "@csstools/selector-specificity": "^3.1.1",
+ "@dual-bundle/import-meta-resolve": "^4.1.0",
"balanced-match": "^2.0.0",
"colord": "^2.9.3",
"cosmiconfig": "^9.0.0",
@@ -6179,7 +6200,7 @@
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"fastest-levenshtein": "^1.0.16",
- "file-entry-cache": "^8.0.0",
+ "file-entry-cache": "^9.0.0",
"global-modules": "^2.0.0",
"globby": "^11.1.0",
"globjoin": "^0.1.4",
@@ -6187,16 +6208,16 @@
"ignore": "^5.3.1",
"imurmurhash": "^0.1.4",
"is-plain-object": "^5.0.0",
- "known-css-properties": "^0.30.0",
+ "known-css-properties": "^0.31.0",
"mathml-tag-names": "^2.1.3",
"meow": "^13.2.0",
- "micromatch": "^4.0.5",
+ "micromatch": "^4.0.7",
"normalize-path": "^3.0.0",
- "picocolors": "^1.0.0",
+ "picocolors": "^1.0.1",
"postcss": "^8.4.38",
"postcss-resolve-nested-selector": "^0.1.1",
"postcss-safe-parser": "^7.0.0",
- "postcss-selector-parser": "^6.0.16",
+ "postcss-selector-parser": "^6.1.0",
"postcss-value-parser": "^4.2.0",
"resolve-from": "^5.0.0",
"string-width": "^4.2.3",
@@ -6211,31 +6232,49 @@
},
"engines": {
"node": ">=18.12.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/stylelint"
}
},
"node_modules/stylelint-config-recommended": {
- "version": "14.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz",
- "integrity": "sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ==",
+ "version": "14.0.1",
+ "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz",
+ "integrity": "sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg==",
"dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/stylelint"
+ }
+ ],
+ "license": "MIT",
"engines": {
"node": ">=18.12.0"
},
"peerDependencies": {
- "stylelint": "^16.0.0"
+ "stylelint": "^16.1.0"
}
},
"node_modules/stylelint-config-standard": {
- "version": "36.0.0",
- "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz",
- "integrity": "sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug==",
+ "version": "36.0.1",
+ "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz",
+ "integrity": "sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw==",
"dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/stylelint"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/stylelint"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "stylelint-config-recommended": "^14.0.0"
+ "stylelint-config-recommended": "^14.0.1"
},
"engines": {
"node": ">=18.12.0"
@@ -6249,6 +6288,7 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=12"
},
@@ -6260,31 +6300,34 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz",
"integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/stylelint/node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-9.0.0.tgz",
+ "integrity": "sha512-6MgEugi8p2tiUhqO7GnPsmbCCzj0YRCwwaTbpGRyKZesjRSzkqkAE9fPp7V2yMs5hwfgbQLgdvSSkGNg1s5Uvw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "flat-cache": "^4.0.0"
+ "flat-cache": "^5.0.0"
},
"engines": {
- "node": ">=16.0.0"
+ "node": ">=18"
}
},
"node_modules/stylelint/node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-5.0.0.tgz",
+ "integrity": "sha512-JrqFmyUl2PnPi1OvLyTVHnQvwQ0S+e6lGSwu8OkAZlSaNIZciTY2H/cOOROxsBA1m/LZNHDsqAgDZt6akWcjsQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "flatted": "^3.2.9",
+ "flatted": "^3.3.1",
"keyv": "^4.5.4"
},
"engines": {
- "node": ">=16"
+ "node": ">=18"
}
},
"node_modules/stylelint/node_modules/resolve-from": {
@@ -6292,6 +6335,7 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -6301,6 +6345,7 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": ">=14"
},
@@ -6313,6 +6358,7 @@
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^6.0.1"
},
@@ -6328,6 +6374,7 @@
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz",
"integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^4.0.1"
@@ -6457,6 +6504,7 @@
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
diff --git a/package.json b/package.json
index 0518b17d..6cb1742c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "netatmo",
- "version": "2.0.0",
+ "version": "2.1.0",
"description": "A module for the MagicMirror² to display information about your rooms climate from your Netatmo system.",
"main": "netatmo.js",
"scripts": {
@@ -37,22 +37,19 @@
},
"homepage": "https://github.com/CFenner/MagicMirror-Netatmo-Module#readme",
"devDependencies": {
- "@snyk/protect": "1.1291.0",
+ "@snyk/protect": "1.1291.1",
"dotenv": "16.3.1",
"eslint": "8.57.0",
"eslint-config-standard": "17.1.0",
"eslint-plugin-import": "2.29.1",
"eslint-plugin-n": "16.6.2",
- "eslint-plugin-promise": "6.1.1",
+ "eslint-plugin-promise": "6.2.0",
"jest": "29.7.0",
"jsonlint-newline-fork": "1.6.8",
"less": "4.2.0",
"markdownlint": "0.32.1",
- "stylelint": "16.5.0",
- "stylelint-config-standard": "36.0.0"
+ "stylelint": "16.6.1",
+ "stylelint-config-standard": "36.0.1"
},
- "snyk": true,
- "dependencies": {
- "@ungap/url-search-params": "0.2.2"
- }
+ "snyk": true
}