-
-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: netatmo api authentication (#182)
* fix issue * fix issue * change test names * add compose file * ignore docker folders * add compose description * fix markdownlint findings * add config * rename test * remove old files
- Loading branch information
Showing
15 changed files
with
463 additions
and
188 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# Ignore all node modules. | ||
node_modules | ||
report | ||
.env | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
config/** | ||
css/ | ||
modules/ | ||
!config/config.js.template |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Integration Testing with Docker Compose | ||
|
||
To test the module in a MagicMirror instance: | ||
|
||
- run `npm run docker:server` to start MagicMirror Docker | ||
- run `npm run docker:clone` to clone the module into the modules folder | ||
- use `docker exec -it mm bash` and `git checkout <branchName>` to load a specific branch | ||
- run `npm run docker:install` to install the modules dependencies | ||
- add the module config to the `config/config.js` | ||
|
||
```yaml | ||
{ | ||
module: 'netatmo', | ||
position: 'bottom_left', | ||
header: 'Netatmo', | ||
config: { | ||
clientId: '', | ||
clientSecret: '', | ||
refresh_token: '', | ||
}, | ||
}, | ||
``` | ||
|
||
- open MagicMirror ui at [`http://0.0.0.0:8080`](http://0.0.0.0:8080) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* MagicMirror² Config Sample | ||
* | ||
* By Michael Teeuw https://michaelteeuw.nl | ||
* MIT Licensed. | ||
* | ||
* For more information on how you can configure this file | ||
* see https://docs.magicmirror.builders/configuration/introduction.html | ||
* and https://docs.magicmirror.builders/modules/configuration.html | ||
* | ||
* You can use environment variables using a `config.js.template` file instead of `config.js` | ||
* which will be converted to `config.js` while starting. For more information | ||
* see https://docs.magicmirror.builders/configuration/introduction.html#enviromnent-variables | ||
*/ | ||
let config = { | ||
address: "0.0.0.0", // Address to listen on, can be: | ||
// - "localhost", "127.0.0.1", "::1" to listen on loopback interface | ||
// - another specific IPv4/6 to listen on a specific interface | ||
// - "0.0.0.0", "::" to listen on any interface | ||
// Default, when address config is left out or empty, is "localhost" | ||
port: 8080, | ||
basePath: "/", // The URL path where MagicMirror² is hosted. If you are using a Reverse proxy | ||
// you must set the sub path here. basePath must end with a / | ||
ipWhitelist: [], // Set [] to allow all IP addresses | ||
// or add a specific IPv4 of 192.168.1.5 : | ||
// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.1.5"], | ||
// or IPv4 range of 192.168.3.0 --> 192.168.3.15 use CIDR format : | ||
// ["127.0.0.1", "::ffff:127.0.0.1", "::1", "::ffff:192.168.3.0/28"], | ||
|
||
useHttps: false, // Support HTTPS or not, default "false" will use HTTP | ||
httpsPrivateKey: "", // HTTPS private key path, only require when useHttps is true | ||
httpsCertificate: "", // HTTPS Certificate path, only require when useHttps is true | ||
|
||
language: "en", | ||
locale: "en-US", | ||
logLevel: ["INFO", "LOG", "WARN", "ERROR"], // Add "DEBUG" for even more logging | ||
timeFormat: 24, | ||
units: "metric", | ||
|
||
modules: [ | ||
{ | ||
module: "alert", | ||
}, | ||
{ | ||
module: 'netatmo', | ||
position: 'bottom_left', | ||
header: 'Netatmo', | ||
config: { | ||
clientId: '${CLIENT_ID}', | ||
clientSecret: '${CLIENT_SECRET}', | ||
refresh_token: '${REFRESH_TOKEN}', | ||
}, | ||
}, | ||
{ | ||
module: "clock", | ||
position: "top_left" | ||
}, | ||
] | ||
}; | ||
|
||
/*************** DO NOT EDIT THE LINE BELOW ***************/ | ||
if (typeof module !== "undefined") {module.exports = config;} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
version: '3' | ||
|
||
services: | ||
magicmirror: | ||
container_name: mm | ||
image: karsten13/magicmirror:fat | ||
volumes: | ||
- ./config:/opt/magic_mirror/config | ||
- ./modules:/opt/magic_mirror/modules | ||
- ./css:/opt/magic_mirror/css | ||
environment: | ||
TZ: Europe/Berlin | ||
MM_SHOW_CURSOR: "true" | ||
env_file: ../.env | ||
ports: | ||
- 8080:8080 | ||
restart: unless-stopped | ||
command: | ||
- npm | ||
- run | ||
- server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
/* Magic Mirror | ||
* Module: MagicMirror-Netatmo-Module | ||
* | ||
* By Christopher Fenner https://github.com/CFenner | ||
* MIT Licensed. | ||
*/ | ||
const fs = require('fs') | ||
const path = require('path') | ||
const fetch = require('sync-fetch') | ||
const URLSearchParams = require('@ungap/url-search-params') | ||
|
||
module.exports = { | ||
notifications: { | ||
AUTH: 'NETATMO_AUTH', | ||
AUTH_RESPONSE: 'NETATMO_AUTH_RESPONSE', | ||
DATA: 'NETATMO_DATA', | ||
DATA_RESPONSE: 'NETATMO_DATA_RESPONSE', | ||
}, | ||
start: function () { | ||
console.log('Netatmo helper started ...') | ||
this.token = null | ||
}, | ||
authenticate: function (config) { | ||
const self = this | ||
self.config = config | ||
|
||
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) | ||
|
||
try { | ||
const result = fetch('https://' + self.config.apiBase + self.config.authEndpoint, { | ||
method: 'POST', | ||
headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, | ||
body: params, | ||
}).json() | ||
|
||
if (result.error) { | ||
throw new Error(result.error + ': ' + result.error_description) | ||
} | ||
|
||
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, { | ||
status: 'OK', | ||
}) | ||
} catch (error) { | ||
console.log('error:', error) | ||
self.sendSocketNotification(self.notifications.AUTH_RESPONSE, { | ||
payloadReturn: error, | ||
status: 'NOTOK', | ||
message: error, | ||
}) | ||
} | ||
}, | ||
loadData: function (config) { | ||
const self = this | ||
self.config = config | ||
|
||
if (self.config.mockData === true) { | ||
self.sendSocketNotification(self.notifications.DATA_RESPONSE, { | ||
payloadReturn: this.mockData(), | ||
status: 'OK', | ||
}) | ||
return | ||
} | ||
if (self.token === null || self.token === undefined) { | ||
self.sendSocketNotification(self.notifications.DATA_RESPONSE, { | ||
payloadReturn: 400, | ||
status: 'INVALID_TOKEN', | ||
message: 'token not set', | ||
}) | ||
return | ||
} | ||
|
||
try { | ||
let result = fetch('https://' + self.config.apiBase + self.config.dataEndpoint, { | ||
headers: { | ||
'Content-Type': 'application/json', | ||
Authorization: `Bearer ${self.token}`, | ||
}, | ||
}) | ||
|
||
if (result.status === 403) { | ||
console.log('status code:', result.status, '\n', result.statusText) | ||
self.sendSocketNotification(self.notifications.DATA_RESPONSE, { | ||
payloadReturn: result.statusText, | ||
status: 'INVALID_TOKEN', | ||
message: result, | ||
}) | ||
return | ||
} | ||
|
||
result = result.json() | ||
|
||
if (result.error) { | ||
throw new Error(result.error.message) | ||
} | ||
|
||
self.sendSocketNotification(self.notifications.DATA_RESPONSE, { | ||
payloadReturn: result.body.devices, | ||
status: 'OK', | ||
}) | ||
} catch (error) { | ||
console.log('error:', error) | ||
self.sendSocketNotification(self.notifications.DATA_RESPONSE, { | ||
payloadReturn: error, | ||
status: 'NOTOK', | ||
message: error, | ||
}) | ||
} | ||
}, | ||
mockData: function () { | ||
const sample = fs.readFileSync(path.join(__dirname, 'sample', 'sample.json'), 'utf8') | ||
return JSON.parse(sample) | ||
}, | ||
socketNotificationReceived: function (notification, payload) { | ||
switch (notification) { | ||
case this.notifications.AUTH: | ||
this.authenticate(payload) | ||
break | ||
case this.notifications.DATA: | ||
this.loadData(payload) | ||
break | ||
} | ||
}, | ||
} |
Oops, something went wrong.