homebridge-weatherlink-cloud 0.1.4 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/config.schema.json +4 -5
- package/index.js +67 -2
- package/package.json +1 -1
package/config.schema.json
CHANGED
|
@@ -25,10 +25,9 @@
|
|
|
25
25
|
"required": true
|
|
26
26
|
},
|
|
27
27
|
"stationId": {
|
|
28
|
-
"title": "Station ID",
|
|
29
|
-
"description": "
|
|
30
|
-
"type": "integer"
|
|
31
|
-
"required": true
|
|
28
|
+
"title": "Station ID (optional)",
|
|
29
|
+
"description": "Leave blank to auto-discover from your account. Only needed if you have more than one station and want to pin a specific one.",
|
|
30
|
+
"type": "integer"
|
|
32
31
|
},
|
|
33
32
|
"pollMinutes": {
|
|
34
33
|
"title": "Poll interval (minutes)",
|
|
@@ -39,7 +38,7 @@
|
|
|
39
38
|
},
|
|
40
39
|
"manufacturer": {
|
|
41
40
|
"title": "Manufacturer",
|
|
42
|
-
"description": "Shown in the Home app accessory
|
|
41
|
+
"description": "Shown in the Home app accessory details. Defaults to Davis Instruments.",
|
|
43
42
|
"type": "string",
|
|
44
43
|
"default": "Davis Instruments"
|
|
45
44
|
},
|
package/index.js
CHANGED
|
@@ -4,6 +4,7 @@ const https = require('https');
|
|
|
4
4
|
|
|
5
5
|
const PLUGIN_NAME = 'homebridge-weatherlink-cloud';
|
|
6
6
|
const PLATFORM_NAME = 'WeatherLinkCloud';
|
|
7
|
+
const PLUGIN_VERSION = require('./package.json').version;
|
|
7
8
|
|
|
8
9
|
let Service, Characteristic;
|
|
9
10
|
|
|
@@ -25,9 +26,19 @@ class WeatherLinkCloudPlatform {
|
|
|
25
26
|
// Polling faster than the data refreshes just wastes API calls.
|
|
26
27
|
this.pollSeconds = (config.pollMinutes || 15) * 60;
|
|
27
28
|
|
|
29
|
+
// Shown in the Home app's accessory details (Manufacturer / Model).
|
|
30
|
+
this.manufacturer = config.manufacturer || 'Davis Instruments';
|
|
31
|
+
this.model = config.model || 'Vantage Vue';
|
|
32
|
+
|
|
28
33
|
this.accessories = new Map(); // UUID -> cached accessory
|
|
29
34
|
|
|
30
|
-
this.api.on('didFinishLaunching', () => {
|
|
35
|
+
this.api.on('didFinishLaunching', async () => {
|
|
36
|
+
try {
|
|
37
|
+
await this.resolveStationId();
|
|
38
|
+
} catch (err) {
|
|
39
|
+
this.log.error('Cannot start: ' + err.message);
|
|
40
|
+
return; // No station ID -> don't create accessories or poll.
|
|
41
|
+
}
|
|
31
42
|
this.setupAccessories();
|
|
32
43
|
this.poll();
|
|
33
44
|
setInterval(() => this.poll(), this.pollSeconds * 1000);
|
|
@@ -51,6 +62,17 @@ class WeatherLinkCloudPlatform {
|
|
|
51
62
|
this.accessories.set(uuid, accessory);
|
|
52
63
|
this.log(`Created accessory: ${name}`);
|
|
53
64
|
}
|
|
65
|
+
|
|
66
|
+
// Set the AccessoryInformation service every time (not just on creation) so
|
|
67
|
+
// that already-cached accessories showing "Default" get corrected on restart.
|
|
68
|
+
// The serial must be UNIQUE per accessory, or HomeKit may merge or misbehave.
|
|
69
|
+
accessory
|
|
70
|
+
.getService(Service.AccessoryInformation)
|
|
71
|
+
.setCharacteristic(Characteristic.Manufacturer, this.manufacturer)
|
|
72
|
+
.setCharacteristic(Characteristic.Model, this.model)
|
|
73
|
+
.setCharacteristic(Characteristic.SerialNumber, `${this.stationId}-${idSuffix}`)
|
|
74
|
+
.setCharacteristic(Characteristic.FirmwareRevision, PLUGIN_VERSION);
|
|
75
|
+
|
|
54
76
|
return accessory;
|
|
55
77
|
}
|
|
56
78
|
|
|
@@ -77,6 +99,14 @@ class WeatherLinkCloudPlatform {
|
|
|
77
99
|
}
|
|
78
100
|
|
|
79
101
|
fetchCurrent() {
|
|
102
|
+
return this.apiGet(`/v2/current/${this.stationId}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
fetchStations() {
|
|
106
|
+
return this.apiGet('/v2/stations');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
apiGet(basePath) {
|
|
80
110
|
// v2 API: api-key as a query param, secret in the X-Api-Secret header.
|
|
81
111
|
// (v2 also supports an older HMAC api-signature scheme — the header
|
|
82
112
|
// method below is the simpler one. Confirm against the official docs:
|
|
@@ -84,7 +114,7 @@ class WeatherLinkCloudPlatform {
|
|
|
84
114
|
return new Promise((resolve, reject) => {
|
|
85
115
|
const options = {
|
|
86
116
|
hostname: 'api.weatherlink.com',
|
|
87
|
-
path:
|
|
117
|
+
path: `${basePath}?api-key=${this.apiKey}`,
|
|
88
118
|
method: 'GET',
|
|
89
119
|
headers: { 'X-Api-Secret': this.apiSecret },
|
|
90
120
|
};
|
|
@@ -104,6 +134,41 @@ class WeatherLinkCloudPlatform {
|
|
|
104
134
|
});
|
|
105
135
|
}
|
|
106
136
|
|
|
137
|
+
// Resolve this.stationId: use the configured value if present, otherwise
|
|
138
|
+
// discover it from /v2/stations. Throws if it can't be determined.
|
|
139
|
+
async resolveStationId() {
|
|
140
|
+
if (this.stationId) {
|
|
141
|
+
this.log(`Using configured station ID ${this.stationId}.`);
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
this.log('No station ID configured — fetching from /v2/stations ...');
|
|
146
|
+
const data = await this.fetchStations();
|
|
147
|
+
const stations = (data && data.stations) || [];
|
|
148
|
+
|
|
149
|
+
if (stations.length === 0) {
|
|
150
|
+
throw new Error('No stations found on this WeatherLink account (check your API key/secret).');
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (stations.length === 1) {
|
|
154
|
+
this.stationId = stations[0].station_id;
|
|
155
|
+
this.log(`Discovered station "${stations[0].station_name}" (ID ${this.stationId}).`);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// More than one station: we can't guess which you want, so list them all
|
|
160
|
+
// and default to the first, telling you how to pin a specific one.
|
|
161
|
+
this.log.warn('Multiple stations found on this account:');
|
|
162
|
+
for (const s of stations) {
|
|
163
|
+
this.log.warn(` - "${s.station_name}" -> stationId ${s.station_id}`);
|
|
164
|
+
}
|
|
165
|
+
this.stationId = stations[0].station_id;
|
|
166
|
+
this.log.warn(
|
|
167
|
+
`Defaulting to "${stations[0].station_name}" (ID ${this.stationId}). ` +
|
|
168
|
+
'Set "stationId" in the plugin config to pin a specific station.'
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
|
|
107
172
|
applyData(data) {
|
|
108
173
|
// The /current payload nests readings under sensors[].data[]. Each sensor
|
|
109
174
|
// block has a sensor_type and data_structure_type; you need to locate the
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-weatherlink-cloud",
|
|
3
3
|
"displayName": "WeatherLink Cloud",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"description": "Exposes Davis WeatherLink (v2 cloud API) weather data to HomeKit via Homebridge.",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"license": "MIT",
|