homebridge-tryfi 1.1.0
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/CHANGELOG.md +43 -0
- package/CHANGES-V3.md +103 -0
- package/LICENSE +201 -0
- package/README.md +139 -0
- package/SUMMARY.md +289 -0
- package/config.schema.json +91 -0
- package/dist/accessory.d.ts +31 -0
- package/dist/accessory.d.ts.map +1 -0
- package/dist/accessory.js +134 -0
- package/dist/accessory.js.map +1 -0
- package/dist/api.d.ts +37 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +365 -0
- package/dist/api.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/platform.d.ts +41 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +168 -0
- package/dist/platform.js.map +1 -0
- package/dist/settings.d.ts +9 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/settings.js +12 -0
- package/dist/settings.js.map +1 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/accessory.ts +172 -0
- package/src/api.ts +409 -0
- package/src/index.ts +10 -0
- package/src/platform.ts +220 -0
- package/src/settings.ts +9 -0
- package/src/types.ts +119 -0
- package/tsconfig.json +25 -0
package/dist/api.js
ADDED
|
@@ -0,0 +1,365 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.TryFiAPI = void 0;
|
|
7
|
+
const axios_1 = __importDefault(require("axios"));
|
|
8
|
+
const axios_cookiejar_support_1 = require("axios-cookiejar-support");
|
|
9
|
+
const tough_cookie_1 = require("tough-cookie");
|
|
10
|
+
/**
|
|
11
|
+
* TryFi API Client - matches pytryfi implementation exactly
|
|
12
|
+
*/
|
|
13
|
+
class TryFiAPI {
|
|
14
|
+
username;
|
|
15
|
+
password;
|
|
16
|
+
log;
|
|
17
|
+
apiUrl = 'https://api.tryfi.com';
|
|
18
|
+
client;
|
|
19
|
+
jar;
|
|
20
|
+
session = null;
|
|
21
|
+
constructor(username, password, log) {
|
|
22
|
+
this.username = username;
|
|
23
|
+
this.password = password;
|
|
24
|
+
this.log = log;
|
|
25
|
+
// Create cookie jar to persist cookies like Python requests.Session()
|
|
26
|
+
this.jar = new tough_cookie_1.CookieJar();
|
|
27
|
+
// Wrap axios with cookie jar support
|
|
28
|
+
this.client = (0, axios_cookiejar_support_1.wrapper)(axios_1.default.create({
|
|
29
|
+
baseURL: this.apiUrl,
|
|
30
|
+
timeout: 30000,
|
|
31
|
+
jar: this.jar,
|
|
32
|
+
withCredentials: true,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Login using REST API (matches pytryfi)
|
|
37
|
+
*/
|
|
38
|
+
async login() {
|
|
39
|
+
try {
|
|
40
|
+
const formData = new URLSearchParams();
|
|
41
|
+
formData.append('email', this.username);
|
|
42
|
+
formData.append('password', this.password);
|
|
43
|
+
const response = await this.client.post('/auth/login', formData, {
|
|
44
|
+
headers: {
|
|
45
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (response.data.error) {
|
|
49
|
+
throw new Error(`Login failed: ${response.data.error.message}`);
|
|
50
|
+
}
|
|
51
|
+
if (!response.data.userId || !response.data.sessionId) {
|
|
52
|
+
throw new Error('Login failed: No session data returned');
|
|
53
|
+
}
|
|
54
|
+
this.session = {
|
|
55
|
+
userId: response.data.userId,
|
|
56
|
+
sessionId: response.data.sessionId,
|
|
57
|
+
};
|
|
58
|
+
// Set JSON header for subsequent GraphQL requests (matches pytryfi.setHeaders())
|
|
59
|
+
this.client.defaults.headers.common['Content-Type'] = 'application/json';
|
|
60
|
+
this.log.info('Successfully authenticated with TryFi');
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
this.log.error('Failed to login to TryFi:', error);
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get all pets using EXACT pytryfi query structure
|
|
69
|
+
*/
|
|
70
|
+
async getPets() {
|
|
71
|
+
await this.ensureAuthenticated();
|
|
72
|
+
// This matches pytryfi's QUERY_CURRENT_USER_FULL_DETAIL + fragments
|
|
73
|
+
const query = `
|
|
74
|
+
query {
|
|
75
|
+
currentUser {
|
|
76
|
+
__typename
|
|
77
|
+
id
|
|
78
|
+
email
|
|
79
|
+
firstName
|
|
80
|
+
lastName
|
|
81
|
+
userHouseholds {
|
|
82
|
+
__typename
|
|
83
|
+
household {
|
|
84
|
+
__typename
|
|
85
|
+
pets {
|
|
86
|
+
__typename
|
|
87
|
+
id
|
|
88
|
+
name
|
|
89
|
+
homeCityState
|
|
90
|
+
gender
|
|
91
|
+
breed {
|
|
92
|
+
__typename
|
|
93
|
+
id
|
|
94
|
+
name
|
|
95
|
+
}
|
|
96
|
+
device {
|
|
97
|
+
__typename
|
|
98
|
+
id
|
|
99
|
+
moduleId
|
|
100
|
+
info
|
|
101
|
+
operationParams {
|
|
102
|
+
__typename
|
|
103
|
+
mode
|
|
104
|
+
ledEnabled
|
|
105
|
+
ledOffAt
|
|
106
|
+
}
|
|
107
|
+
lastConnectionState {
|
|
108
|
+
__typename
|
|
109
|
+
date
|
|
110
|
+
... on ConnectedToUser {
|
|
111
|
+
user {
|
|
112
|
+
__typename
|
|
113
|
+
id
|
|
114
|
+
firstName
|
|
115
|
+
lastName
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
... on ConnectedToBase {
|
|
119
|
+
chargingBase {
|
|
120
|
+
__typename
|
|
121
|
+
id
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
... on ConnectedToCellular {
|
|
125
|
+
signalStrengthPercent
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
`;
|
|
135
|
+
try {
|
|
136
|
+
const response = await this.client.post('/graphql', { query });
|
|
137
|
+
if (response.data.errors) {
|
|
138
|
+
throw new Error(`GraphQL error: ${response.data.errors[0].message}`);
|
|
139
|
+
}
|
|
140
|
+
if (!response.data.data?.currentUser?.userHouseholds) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
// Flatten pets from all households
|
|
144
|
+
const pets = [];
|
|
145
|
+
for (const userHousehold of response.data.data.currentUser.userHouseholds) {
|
|
146
|
+
if (userHousehold.household?.pets) {
|
|
147
|
+
for (const pet of userHousehold.household.pets) {
|
|
148
|
+
if (!pet.device) {
|
|
149
|
+
this.log.warn(`Pet ${pet.name} has no device, skipping`);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
// Parse device info JSON object
|
|
153
|
+
const deviceInfo = pet.device.info || {};
|
|
154
|
+
const batteryPercent = parseInt(deviceInfo.batteryPercent) || 0;
|
|
155
|
+
const isCharging = deviceInfo.isCharging || false;
|
|
156
|
+
// Get location data for this pet
|
|
157
|
+
const location = await this.getPetLocation(pet.id);
|
|
158
|
+
// Determine connection status
|
|
159
|
+
const connectionState = pet.device.lastConnectionState;
|
|
160
|
+
const isCharging2 = connectionState?.__typename === 'ConnectedToBase';
|
|
161
|
+
const connectedToUser = connectionState?.__typename === 'ConnectedToUser'
|
|
162
|
+
? connectionState.user?.firstName || null
|
|
163
|
+
: null;
|
|
164
|
+
pets.push({
|
|
165
|
+
petId: pet.id,
|
|
166
|
+
name: pet.name,
|
|
167
|
+
breed: pet.breed?.name || 'Unknown',
|
|
168
|
+
moduleId: pet.device.moduleId,
|
|
169
|
+
batteryPercent,
|
|
170
|
+
isCharging: isCharging || isCharging2,
|
|
171
|
+
ledEnabled: pet.device.operationParams?.ledEnabled || false,
|
|
172
|
+
mode: pet.device.operationParams?.mode || 'NORMAL',
|
|
173
|
+
connectedToUser,
|
|
174
|
+
...location,
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
this.log.debug(`Retrieved ${pets.length} pet(s) from TryFi`);
|
|
180
|
+
return pets;
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
this.log.error('Failed to get pets:', error);
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Get pet location - matches pytryfi's getCurrentPetLocation
|
|
189
|
+
*/
|
|
190
|
+
async getPetLocation(petId) {
|
|
191
|
+
const query = `
|
|
192
|
+
query {
|
|
193
|
+
pet(id: "${petId}") {
|
|
194
|
+
ongoingActivity {
|
|
195
|
+
__typename
|
|
196
|
+
start
|
|
197
|
+
areaName
|
|
198
|
+
... on OngoingWalk {
|
|
199
|
+
positions {
|
|
200
|
+
__typename
|
|
201
|
+
date
|
|
202
|
+
position {
|
|
203
|
+
__typename
|
|
204
|
+
latitude
|
|
205
|
+
longitude
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
... on OngoingRest {
|
|
210
|
+
position {
|
|
211
|
+
__typename
|
|
212
|
+
latitude
|
|
213
|
+
longitude
|
|
214
|
+
}
|
|
215
|
+
place {
|
|
216
|
+
__typename
|
|
217
|
+
id
|
|
218
|
+
name
|
|
219
|
+
address
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
`;
|
|
226
|
+
try {
|
|
227
|
+
const response = await this.client.post('/graphql', { query });
|
|
228
|
+
if (response.data.errors) {
|
|
229
|
+
this.log.warn(`Failed to get location for pet ${petId}:`, response.data.errors[0].message);
|
|
230
|
+
return {
|
|
231
|
+
latitude: 0,
|
|
232
|
+
longitude: 0,
|
|
233
|
+
areaName: null,
|
|
234
|
+
placeName: null,
|
|
235
|
+
placeAddress: null,
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
const activity = response.data.data?.pet?.ongoingActivity;
|
|
239
|
+
if (!activity) {
|
|
240
|
+
return {
|
|
241
|
+
latitude: 0,
|
|
242
|
+
longitude: 0,
|
|
243
|
+
areaName: null,
|
|
244
|
+
placeName: null,
|
|
245
|
+
placeAddress: null,
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
const areaName = activity.areaName || null;
|
|
249
|
+
let latitude = 0;
|
|
250
|
+
let longitude = 0;
|
|
251
|
+
let placeName = null;
|
|
252
|
+
let placeAddress = null;
|
|
253
|
+
if (activity.__typename === 'OngoingRest') {
|
|
254
|
+
latitude = activity.position?.latitude || 0;
|
|
255
|
+
longitude = activity.position?.longitude || 0;
|
|
256
|
+
placeName = activity.place?.name || null;
|
|
257
|
+
placeAddress = activity.place?.address || null;
|
|
258
|
+
}
|
|
259
|
+
else if (activity.__typename === 'OngoingWalk' && activity.positions?.length > 0) {
|
|
260
|
+
const lastPosition = activity.positions[activity.positions.length - 1];
|
|
261
|
+
latitude = lastPosition.position?.latitude || 0;
|
|
262
|
+
longitude = lastPosition.position?.longitude || 0;
|
|
263
|
+
}
|
|
264
|
+
return { latitude, longitude, areaName, placeName, placeAddress };
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
this.log.warn(`Failed to get location for pet ${petId}:`, error);
|
|
268
|
+
return {
|
|
269
|
+
latitude: 0,
|
|
270
|
+
longitude: 0,
|
|
271
|
+
areaName: null,
|
|
272
|
+
placeName: null,
|
|
273
|
+
placeAddress: null,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Set LED on/off - matches pytryfi's turnOnOffLed
|
|
279
|
+
*/
|
|
280
|
+
async setLedState(moduleId, ledEnabled) {
|
|
281
|
+
await this.ensureAuthenticated();
|
|
282
|
+
const mutation = `
|
|
283
|
+
mutation UpdateDeviceOperationParams($input: UpdateDeviceOperationParamsInput!) {
|
|
284
|
+
updateDeviceOperationParams(input: $input) {
|
|
285
|
+
__typename
|
|
286
|
+
id
|
|
287
|
+
moduleId
|
|
288
|
+
operationParams {
|
|
289
|
+
__typename
|
|
290
|
+
mode
|
|
291
|
+
ledEnabled
|
|
292
|
+
ledOffAt
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
`;
|
|
297
|
+
try {
|
|
298
|
+
const response = await this.client.post('/graphql', {
|
|
299
|
+
query: mutation,
|
|
300
|
+
variables: {
|
|
301
|
+
input: {
|
|
302
|
+
moduleId,
|
|
303
|
+
ledEnabled,
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
});
|
|
307
|
+
if (response.data.errors) {
|
|
308
|
+
throw new Error(`Failed to set LED: ${response.data.errors[0].message}`);
|
|
309
|
+
}
|
|
310
|
+
this.log.debug(`Set LED ${ledEnabled ? 'on' : 'off'} for module ${moduleId}`);
|
|
311
|
+
}
|
|
312
|
+
catch (error) {
|
|
313
|
+
this.log.error('Failed to set LED state:', error);
|
|
314
|
+
throw error;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
/**
|
|
318
|
+
* Set Lost Dog Mode - matches pytryfi's setLostDogMode
|
|
319
|
+
*/
|
|
320
|
+
async setLostDogMode(moduleId, isLost) {
|
|
321
|
+
await this.ensureAuthenticated();
|
|
322
|
+
const mode = isLost ? 'LOST_DOG' : 'NORMAL';
|
|
323
|
+
const mutation = `
|
|
324
|
+
mutation UpdateDeviceOperationParams($input: UpdateDeviceOperationParamsInput!) {
|
|
325
|
+
updateDeviceOperationParams(input: $input) {
|
|
326
|
+
__typename
|
|
327
|
+
id
|
|
328
|
+
moduleId
|
|
329
|
+
operationParams {
|
|
330
|
+
__typename
|
|
331
|
+
mode
|
|
332
|
+
ledEnabled
|
|
333
|
+
ledOffAt
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
`;
|
|
338
|
+
try {
|
|
339
|
+
const response = await this.client.post('/graphql', {
|
|
340
|
+
query: mutation,
|
|
341
|
+
variables: {
|
|
342
|
+
input: {
|
|
343
|
+
moduleId,
|
|
344
|
+
mode,
|
|
345
|
+
},
|
|
346
|
+
},
|
|
347
|
+
});
|
|
348
|
+
if (response.data.errors) {
|
|
349
|
+
throw new Error(`Failed to set lost mode: ${response.data.errors[0].message}`);
|
|
350
|
+
}
|
|
351
|
+
this.log.info(`Set Lost Dog Mode ${isLost ? 'ON' : 'OFF'} for module ${moduleId}`);
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
this.log.error('Failed to set lost dog mode:', error);
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
async ensureAuthenticated() {
|
|
359
|
+
if (!this.session) {
|
|
360
|
+
await this.login();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
exports.TryFiAPI = TryFiAPI;
|
|
365
|
+
//# sourceMappingURL=api.js.map
|
package/dist/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,YAAY,CAAC;AAIjC;;GAEG;yBACO,KAAK,GAAG;AAAlB,kBAEE"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
const platform_1 = require("./platform");
|
|
3
|
+
const settings_1 = require("./settings");
|
|
4
|
+
module.exports = (api) => {
|
|
5
|
+
api.registerPlatform(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, platform_1.TryFiPlatform);
|
|
6
|
+
};
|
|
7
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,yCAA2C;AAC3C,yCAAwD;AAKxD,iBAAS,CAAC,GAAQ,EAAE,EAAE;IACpB,GAAG,CAAC,gBAAgB,CAAC,sBAAW,EAAE,wBAAa,EAAE,wBAAa,CAAC,CAAC;AAClE,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { API, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service, Characteristic } from 'homebridge';
|
|
2
|
+
import { TryFiAPI } from './api';
|
|
3
|
+
import { TryFiCollarAccessory } from './accessory';
|
|
4
|
+
import { TryFiPlatformConfig } from './types';
|
|
5
|
+
/**
|
|
6
|
+
* TryFi Platform Plugin
|
|
7
|
+
*/
|
|
8
|
+
export declare class TryFiPlatform implements DynamicPlatformPlugin {
|
|
9
|
+
readonly log: Logger;
|
|
10
|
+
readonly homebridgeApi: API;
|
|
11
|
+
readonly Service: typeof Service;
|
|
12
|
+
readonly Characteristic: typeof Characteristic;
|
|
13
|
+
readonly config: TryFiPlatformConfig;
|
|
14
|
+
readonly accessories: PlatformAccessory[];
|
|
15
|
+
readonly collarAccessories: Map<string, TryFiCollarAccessory>;
|
|
16
|
+
readonly tryfiApi: TryFiAPI;
|
|
17
|
+
readonly api: TryFiAPI;
|
|
18
|
+
private pollingInterval?;
|
|
19
|
+
constructor(log: Logger, config: PlatformConfig, homebridgeApi: API);
|
|
20
|
+
/**
|
|
21
|
+
* This function is invoked when homebridge restores cached accessories from disk at startup.
|
|
22
|
+
*/
|
|
23
|
+
configureAccessory(accessory: PlatformAccessory): void;
|
|
24
|
+
/**
|
|
25
|
+
* Discover TryFi collars and create accessories
|
|
26
|
+
*/
|
|
27
|
+
discoverDevices(): Promise<void>;
|
|
28
|
+
/**
|
|
29
|
+
* Start polling TryFi API for updates
|
|
30
|
+
*/
|
|
31
|
+
private startPolling;
|
|
32
|
+
/**
|
|
33
|
+
* Poll TryFi API for device updates
|
|
34
|
+
*/
|
|
35
|
+
private pollDevices;
|
|
36
|
+
/**
|
|
37
|
+
* Stop polling when platform is shutting down
|
|
38
|
+
*/
|
|
39
|
+
shutdown(): void;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=platform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,qBAAqB,EACrB,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,OAAO,EACP,cAAc,EACf,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C;;GAEG;AACH,qBAAa,aAAc,YAAW,qBAAqB;aAavC,GAAG,EAAE,MAAM;aAEX,aAAa,EAAE,GAAG;IAdpC,SAAgB,OAAO,EAAE,OAAO,OAAO,CAAC;IACxC,SAAgB,cAAc,EAAE,OAAO,cAAc,CAAC;IAEtD,SAAgB,MAAM,EAAE,mBAAmB,CAAC;IAC5C,SAAgB,WAAW,EAAE,iBAAiB,EAAE,CAAM;IACtD,SAAgB,iBAAiB,EAAE,GAAG,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAa;IAEjF,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC,SAAgB,GAAG,EAAE,QAAQ,CAAC;IAC9B,OAAO,CAAC,eAAe,CAAC,CAAiB;gBAGvB,GAAG,EAAE,MAAM,EAC3B,MAAM,EAAE,cAAc,EACN,aAAa,EAAE,GAAG;IA2BpC;;OAEG;IACH,kBAAkB,CAAC,SAAS,EAAE,iBAAiB;IAK/C;;OAEG;IACG,eAAe;IAmGrB;;OAEG;IACH,OAAO,CAAC,YAAY;IAgBpB;;OAEG;YACW,WAAW;IAqBzB;;OAEG;IACH,QAAQ;CAKT"}
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TryFiPlatform = void 0;
|
|
4
|
+
const api_1 = require("./api");
|
|
5
|
+
const accessory_1 = require("./accessory");
|
|
6
|
+
/**
|
|
7
|
+
* TryFi Platform Plugin
|
|
8
|
+
*/
|
|
9
|
+
class TryFiPlatform {
|
|
10
|
+
log;
|
|
11
|
+
homebridgeApi;
|
|
12
|
+
Service;
|
|
13
|
+
Characteristic;
|
|
14
|
+
config;
|
|
15
|
+
accessories = [];
|
|
16
|
+
collarAccessories = new Map();
|
|
17
|
+
tryfiApi;
|
|
18
|
+
api; // Alias for accessory use
|
|
19
|
+
pollingInterval;
|
|
20
|
+
constructor(log, config, homebridgeApi) {
|
|
21
|
+
this.log = log;
|
|
22
|
+
this.homebridgeApi = homebridgeApi;
|
|
23
|
+
this.Service = this.homebridgeApi.hap.Service;
|
|
24
|
+
this.Characteristic = this.homebridgeApi.hap.Characteristic;
|
|
25
|
+
// Cast config to our platform config type
|
|
26
|
+
this.config = config;
|
|
27
|
+
// Validate config
|
|
28
|
+
if (!this.config.username || !this.config.password) {
|
|
29
|
+
this.log.error('TryFi username and password are required in config');
|
|
30
|
+
throw new Error('Missing required config');
|
|
31
|
+
}
|
|
32
|
+
// Create API client
|
|
33
|
+
this.tryfiApi = new api_1.TryFiAPI(this.config.username, this.config.password, log);
|
|
34
|
+
this.api = this.tryfiApi; // Alias for accessory use
|
|
35
|
+
this.log.debug('Finished initializing platform:', config.name);
|
|
36
|
+
// When this event is fired it means Homebridge has restored all cached accessories
|
|
37
|
+
this.homebridgeApi.on('didFinishLaunching', () => {
|
|
38
|
+
log.debug('Executed didFinishLaunching callback');
|
|
39
|
+
this.discoverDevices();
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* This function is invoked when homebridge restores cached accessories from disk at startup.
|
|
44
|
+
*/
|
|
45
|
+
configureAccessory(accessory) {
|
|
46
|
+
this.log.info('Loading accessory from cache:', accessory.displayName);
|
|
47
|
+
this.accessories.push(accessory);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Discover TryFi collars and create accessories
|
|
51
|
+
*/
|
|
52
|
+
async discoverDevices() {
|
|
53
|
+
try {
|
|
54
|
+
// Login and get pets
|
|
55
|
+
await this.tryfiApi.login();
|
|
56
|
+
const allPets = await this.tryfiApi.getPets();
|
|
57
|
+
// Filter out ignored pets (case-insensitive)
|
|
58
|
+
const ignoredPets = (this.config.ignoredPets || []).map(name => name.toLowerCase());
|
|
59
|
+
const pets = allPets.filter(pet => !ignoredPets.includes(pet.name.toLowerCase()));
|
|
60
|
+
if (ignoredPets.length > 0) {
|
|
61
|
+
const ignoredCount = allPets.length - pets.length;
|
|
62
|
+
if (ignoredCount > 0) {
|
|
63
|
+
this.log.info(`Ignoring ${ignoredCount} pet(s) based on configuration`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
this.log.info(`Discovered ${pets.length} TryFi collar(s)`);
|
|
67
|
+
// Track discovered pet IDs
|
|
68
|
+
const discoveredPetIds = new Set();
|
|
69
|
+
for (const pet of pets) {
|
|
70
|
+
discoveredPetIds.add(pet.petId);
|
|
71
|
+
// Generate unique ID for this accessory
|
|
72
|
+
const uuid = this.homebridgeApi.hap.uuid.generate(pet.petId);
|
|
73
|
+
// Check if accessory already exists
|
|
74
|
+
const existingAccessory = this.accessories.find((accessory) => accessory.UUID === uuid);
|
|
75
|
+
if (existingAccessory) {
|
|
76
|
+
// Restore existing accessory
|
|
77
|
+
this.log.info('Restoring existing accessory from cache:', pet.name);
|
|
78
|
+
existingAccessory.context.pet = pet;
|
|
79
|
+
// Create collar accessory handler
|
|
80
|
+
const collarAccessory = new accessory_1.TryFiCollarAccessory(this, existingAccessory, pet);
|
|
81
|
+
this.collarAccessories.set(pet.petId, collarAccessory);
|
|
82
|
+
// Update reachability
|
|
83
|
+
this.homebridgeApi.updatePlatformAccessories([existingAccessory]);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// Create new accessory
|
|
87
|
+
this.log.info('Adding new accessory:', pet.name);
|
|
88
|
+
const accessory = new this.homebridgeApi.platformAccessory(pet.name, uuid);
|
|
89
|
+
accessory.context.pet = pet;
|
|
90
|
+
// Create collar accessory handler
|
|
91
|
+
const collarAccessory = new accessory_1.TryFiCollarAccessory(this, accessory, pet);
|
|
92
|
+
this.collarAccessories.set(pet.petId, collarAccessory);
|
|
93
|
+
// Register new accessory
|
|
94
|
+
this.homebridgeApi.registerPlatformAccessories('homebridge-tryfi', 'TryFi', [
|
|
95
|
+
accessory,
|
|
96
|
+
]);
|
|
97
|
+
this.accessories.push(accessory);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Remove accessories for pets that no longer exist
|
|
101
|
+
const accessoriesToRemove = this.accessories.filter((accessory) => !discoveredPetIds.has(accessory.context.pet?.petId));
|
|
102
|
+
if (accessoriesToRemove.length > 0) {
|
|
103
|
+
this.log.info(`Removing ${accessoriesToRemove.length} accessory(ies) for deleted pets`);
|
|
104
|
+
this.homebridgeApi.unregisterPlatformAccessories('homebridge-tryfi', 'TryFi', accessoriesToRemove);
|
|
105
|
+
// Remove from our tracking
|
|
106
|
+
for (const accessory of accessoriesToRemove) {
|
|
107
|
+
const index = this.accessories.indexOf(accessory);
|
|
108
|
+
if (index > -1) {
|
|
109
|
+
this.accessories.splice(index, 1);
|
|
110
|
+
}
|
|
111
|
+
this.collarAccessories.delete(accessory.context.pet?.petId);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Start polling for updates
|
|
115
|
+
this.startPolling();
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
this.log.error('Failed to discover TryFi devices:', error);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Start polling TryFi API for updates
|
|
123
|
+
*/
|
|
124
|
+
startPolling() {
|
|
125
|
+
const pollingInterval = (this.config.pollingInterval || 60) * 1000;
|
|
126
|
+
this.log.info(`Starting polling every ${pollingInterval / 1000} seconds`);
|
|
127
|
+
// Clear any existing interval
|
|
128
|
+
if (this.pollingInterval) {
|
|
129
|
+
clearInterval(this.pollingInterval);
|
|
130
|
+
}
|
|
131
|
+
// Poll immediately, then at intervals
|
|
132
|
+
this.pollDevices();
|
|
133
|
+
this.pollingInterval = setInterval(() => {
|
|
134
|
+
this.pollDevices();
|
|
135
|
+
}, pollingInterval);
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Poll TryFi API for device updates
|
|
139
|
+
*/
|
|
140
|
+
async pollDevices() {
|
|
141
|
+
try {
|
|
142
|
+
const allPets = await this.tryfiApi.getPets();
|
|
143
|
+
// Filter out ignored pets (case-insensitive)
|
|
144
|
+
const ignoredPets = (this.config.ignoredPets || []).map(name => name.toLowerCase());
|
|
145
|
+
const pets = allPets.filter(pet => !ignoredPets.includes(pet.name.toLowerCase()));
|
|
146
|
+
for (const pet of pets) {
|
|
147
|
+
const accessory = this.collarAccessories.get(pet.petId);
|
|
148
|
+
if (accessory) {
|
|
149
|
+
accessory.updatePetData(pet);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
this.log.debug(`Updated ${pets.length} collar(s)`);
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
this.log.error('Failed to poll TryFi API:', error);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Stop polling when platform is shutting down
|
|
160
|
+
*/
|
|
161
|
+
shutdown() {
|
|
162
|
+
if (this.pollingInterval) {
|
|
163
|
+
clearInterval(this.pollingInterval);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
exports.TryFiPlatform = TryFiPlatform;
|
|
168
|
+
//# sourceMappingURL=platform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":";;;AASA,+BAAiC;AACjC,2CAAmD;AAGnD;;GAEG;AACH,MAAa,aAAa;IAaN;IAEA;IAdF,OAAO,CAAiB;IACxB,cAAc,CAAwB;IAEtC,MAAM,CAAsB;IAC5B,WAAW,GAAwB,EAAE,CAAC;IACtC,iBAAiB,GAAsC,IAAI,GAAG,EAAE,CAAC;IAEjE,QAAQ,CAAW;IACnB,GAAG,CAAW,CAAC,0BAA0B;IACjD,eAAe,CAAkB;IAEzC,YACkB,GAAW,EAC3B,MAAsB,EACN,aAAkB;QAFlB,QAAG,GAAH,GAAG,CAAQ;QAEX,kBAAa,GAAb,aAAa,CAAK;QAElC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC;QAC9C,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,cAAc,CAAC;QAE5D,0CAA0C;QAC1C,IAAI,CAAC,MAAM,GAAG,MAA6B,CAAC;QAE5C,kBAAkB;QAClB,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,oDAAoD,CAAC,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,QAAQ,GAAG,IAAI,cAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QAC9E,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,0BAA0B;QAEpD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,iCAAiC,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAE/D,mFAAmF;QACnF,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;YAC/C,GAAG,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;YAClD,IAAI,CAAC,eAAe,EAAE,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACH,kBAAkB,CAAC,SAA4B;QAC7C,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,SAAS,CAAC,WAAW,CAAC,CAAC;QACtE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe;QACnB,IAAI,CAAC;YACH,qBAAqB;YACrB,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAE9C,6CAA6C;YAC7C,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACpF,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YAElF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;gBAClD,IAAI,YAAY,GAAG,CAAC,EAAE,CAAC;oBACrB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,YAAY,gCAAgC,CAAC,CAAC;gBAC1E,CAAC;YACH,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,MAAM,kBAAkB,CAAC,CAAC;YAE3D,2BAA2B;YAC3B,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;YAE3C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAEhC,wCAAwC;gBACxC,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBAE7D,oCAAoC;gBACpC,MAAM,iBAAiB,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,CAC7C,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CACvC,CAAC;gBAEF,IAAI,iBAAiB,EAAE,CAAC;oBACtB,6BAA6B;oBAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0CAA0C,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;oBACpE,iBAAiB,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;oBAEpC,kCAAkC;oBAClC,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAC9C,IAAI,EACJ,iBAAiB,EACjB,GAAG,CACJ,CAAC;oBACF,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;oBAEvD,sBAAsB;oBACtB,IAAI,CAAC,aAAa,CAAC,yBAAyB,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;gBACpE,CAAC;qBAAM,CAAC;oBACN,uBAAuB;oBACvB,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;oBAEjD,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;oBAC3E,SAAS,CAAC,OAAO,CAAC,GAAG,GAAG,GAAG,CAAC;oBAE5B,kCAAkC;oBAClC,MAAM,eAAe,GAAG,IAAI,gCAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;oBACvE,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC;oBAEvD,yBAAyB;oBACzB,IAAI,CAAC,aAAa,CAAC,2BAA2B,CAAC,kBAAkB,EAAE,OAAO,EAAE;wBAC1E,SAAS;qBACV,CAAC,CAAC;oBACH,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBACnC,CAAC;YACH,CAAC;YAED,mDAAmD;YACnD,MAAM,mBAAmB,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CACjD,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CACnE,CAAC;YAEF,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,IAAI,CAAC,GAAG,CAAC,IAAI,CACX,YAAY,mBAAmB,CAAC,MAAM,kCAAkC,CACzE,CAAC;gBACF,IAAI,CAAC,aAAa,CAAC,6BAA6B,CAC9C,kBAAkB,EAClB,OAAO,EACP,mBAAmB,CACpB,CAAC;gBAEF,2BAA2B;gBAC3B,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE,CAAC;oBAC5C,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAClD,IAAI,KAAK,GAAG,CAAC,CAAC,EAAE,CAAC;wBACf,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;oBACpC,CAAC;oBACD,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;gBAC9D,CAAC;YACH,CAAC;YAED,4BAA4B;YAC5B,IAAI,CAAC,YAAY,EAAE,CAAC;QACtB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,mCAAmC,EAAE,KAAK,CAAC,CAAC;QAC7D,CAAC;IACH,CAAC;IAED;;OAEG;IACK,YAAY;QAClB,MAAM,eAAe,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,eAAe,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACnE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,0BAA0B,eAAe,GAAG,IAAI,UAAU,CAAC,CAAC;QAE1E,8BAA8B;QAC9B,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACtC,CAAC;QAED,sCAAsC;QACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACnB,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE;YACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACrB,CAAC,EAAE,eAAe,CAAC,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,WAAW;QACvB,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;YAE9C,6CAA6C;YAC7C,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACpF,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;YAElF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;gBACvB,MAAM,SAAS,GAAG,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;gBACxD,IAAI,SAAS,EAAE,CAAC;oBACd,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC;YACH,CAAC;YAED,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,MAAM,YAAY,CAAC,CAAC;QACrD,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACzB,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QACtC,CAAC;IACH,CAAC;CACF;AA3MD,sCA2MC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
3
|
+
*/
|
|
4
|
+
export declare const PLATFORM_NAME = "TryFi";
|
|
5
|
+
/**
|
|
6
|
+
* This must match the name of your plugin as defined the package.json
|
|
7
|
+
*/
|
|
8
|
+
export declare const PLUGIN_NAME = "homebridge-tryfi";
|
|
9
|
+
//# sourceMappingURL=settings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,aAAa,UAAU,CAAC;AAErC;;GAEG;AACH,eAAO,MAAM,WAAW,qBAAqB,CAAC"}
|
package/dist/settings.js
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PLUGIN_NAME = exports.PLATFORM_NAME = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
|
6
|
+
*/
|
|
7
|
+
exports.PLATFORM_NAME = 'TryFi';
|
|
8
|
+
/**
|
|
9
|
+
* This must match the name of your plugin as defined the package.json
|
|
10
|
+
*/
|
|
11
|
+
exports.PLUGIN_NAME = 'homebridge-tryfi';
|
|
12
|
+
//# sourceMappingURL=settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":";;;AAAA;;GAEG;AACU,QAAA,aAAa,GAAG,OAAO,CAAC;AAErC;;GAEG;AACU,QAAA,WAAW,GAAG,kBAAkB,CAAC"}
|