@pipechela/ewelink-api 1.0.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +22 -0
  3. package/index.d.ts +223 -0
  4. package/main.js +114 -0
  5. package/package.json +67 -0
  6. package/src/classes/ChangeStateZeroconf.js +34 -0
  7. package/src/classes/DevicePowerUsageRaw.js +58 -0
  8. package/src/classes/WebSocket.js +57 -0
  9. package/src/classes/Zeroconf.js +91 -0
  10. package/src/data/constants.js +7 -0
  11. package/src/data/devices-channel-length.json +20 -0
  12. package/src/data/devices-type-uuid.json +55 -0
  13. package/src/data/errors.js +23 -0
  14. package/src/helpers/device-control.js +58 -0
  15. package/src/helpers/ewelink.js +68 -0
  16. package/src/helpers/utilities.js +29 -0
  17. package/src/mixins/checkDeviceUpdate.js +48 -0
  18. package/src/mixins/checkDevicesUpdates.js +54 -0
  19. package/src/mixins/deviceControl.js +272 -0
  20. package/src/mixins/getCredentials.js +54 -0
  21. package/src/mixins/getDevice.js +37 -0
  22. package/src/mixins/getDeviceChannelCount.js +26 -0
  23. package/src/mixins/getDeviceCurrentTH.js +55 -0
  24. package/src/mixins/getDeviceIP.js +15 -0
  25. package/src/mixins/getDevicePowerState.js +47 -0
  26. package/src/mixins/getDevicePowerUsage.js +27 -0
  27. package/src/mixins/getDevicePowerUsageRaw.js +30 -0
  28. package/src/mixins/getDevices.js +37 -0
  29. package/src/mixins/getFirmwareVersion.js +23 -0
  30. package/src/mixins/getRegion.js +23 -0
  31. package/src/mixins/index.js +43 -0
  32. package/src/mixins/makeRequest.js +54 -0
  33. package/src/mixins/openWebSocket.js +44 -0
  34. package/src/mixins/saveDevicesCache.js +29 -0
  35. package/src/mixins/setDevicePowerState.js +90 -0
  36. package/src/mixins/toggleDevice.js +13 -0
  37. package/src/parsers/parseFirmwareUpdates.js +16 -0
  38. package/src/parsers/parsePowerUsage.js +38 -0
  39. package/src/payloads/credentialsPayload.js +13 -0
  40. package/src/payloads/deviceStatus.js +12 -0
  41. package/src/payloads/wssLoginPayload.js +19 -0
  42. package/src/payloads/wssUpdatePayload.js +17 -0
  43. package/src/payloads/zeroConfUpdatePayload.js +17 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Martin M.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,22 @@
1
+ # @pipechela/ewelink-api
2
+ > eWeLink API for JavaScript (Fork with fixes)
3
+
4
+ This repository is a fork of [skydiver/ewelink-api](https://github.com/skydiver/ewelink-api) with the following changes:
5
+ - fixed mac address parsing
6
+
7
+ ## Key features
8
+ * can run on browsers, node scripts or serverless environment
9
+ * set on/off devices
10
+ * get power consumption on devices like Sonoff POW
11
+ * listen for devices events
12
+ * using zeroconf (LAN mode), no internet connection required
13
+
14
+
15
+ ## Installation
16
+ ```sh
17
+ npm install @pipechela/ewelink-api
18
+ ```
19
+
20
+
21
+ ## Usage
22
+ Check library documentation and examples in the `docs` folder or at the [original repository](https://github.com/skydiver/ewelink-api/tree/master/docs).
package/index.d.ts ADDED
@@ -0,0 +1,223 @@
1
+ // Type definitions for ewelink-api
2
+ // Definitions by: Alexander Méhes https://github.com/BMXsanko
3
+
4
+ declare module '@pipechela/ewelink-api' {
5
+ export default eWelink;
6
+
7
+ class eWelink {
8
+ constructor({ }: { email: string; password: string; } | { at: string; } | { at: string; apiKey: string; });
9
+ /**
10
+ * Login into eWeLink API and get auth credentials.
11
+ */
12
+ login(): Promise<LoginInfo>
13
+ /**
14
+ * Opens a socket connection to eWeLink and listen for real-time events.
15
+ */
16
+ openWebSocket(callback: (data: {}) => void): Promise<any>
17
+ /**
18
+ * Returns a list of devices associated to logged account.
19
+ */
20
+ getDevices(): Promise<Device[]>
21
+ /**
22
+ * Return information for specified device.
23
+ */
24
+ getDevice(deviceId: string): Promise<Device>
25
+ /**
26
+ * Query for specified device power status.
27
+ */
28
+ getDevicePowerState(deviceId: string, channel?: number): Promise<DeviceState>
29
+ /**
30
+ * Change specified device power state.
31
+ */
32
+ setDevicePowerState(deviceId: string, state?: string, channel?: number): Promise<DeviceState>
33
+ /**
34
+ * Switch specified device current power state.
35
+ */
36
+ toggleDevice(deviceId: string, channel?: number): Promise<DeviceState>
37
+ /**
38
+ * Returns current month power usage on device who supports electricity records, like Sonoff POW.
39
+ */
40
+ getDevicePowerUsage(deviceId: string): Promise<PowerUsage>
41
+ /**
42
+ * Return current temperature and humidity for specified device.
43
+ */
44
+ getDeviceCurrentTH(deviceId: string): Promise<TemperatureHumidity>
45
+ /**
46
+ * Return current temperature for specified device.
47
+ */
48
+ getDeviceCurrentTemperature(deviceId: string): Promise<TemperatureHumidity>
49
+ /**
50
+ * Return current temperature for specified device.
51
+ */
52
+ getDeviceCurrentHumidity(deviceId: string): Promise<TemperatureHumidity>
53
+ /**
54
+ * Return total channels for specified device.
55
+ */
56
+ getDeviceChannelCount(deviceId: string): Promise<SwitchCount>
57
+ /**
58
+ * Return firmware version for specified device.
59
+ */
60
+ getFirmwareVersion(deviceId: string): Promise<FirmwareVersion>
61
+ }
62
+
63
+ export interface Device {
64
+ _id: string;
65
+ name: string;
66
+ type: string;
67
+ deviceid: string;
68
+ apikey: string;
69
+ extra: Extra2;
70
+ __v: number;
71
+ onlineTime: string;
72
+ ip: string;
73
+ location: string;
74
+ offlineTime: string;
75
+ deviceStatus: string;
76
+ tags: Tags;
77
+ settings: Settings;
78
+ devGroups: any[];
79
+ groups: any[];
80
+ params: Params;
81
+ online: boolean;
82
+ createdAt: string;
83
+ group: string;
84
+ sharedTo: any[];
85
+ devicekey: string;
86
+ deviceUrl: string;
87
+ brandName: string;
88
+ showBrand: boolean;
89
+ brandLogoUrl: string;
90
+ productModel: string;
91
+ devConfig: DevConfig;
92
+ uiid: number;
93
+ }
94
+
95
+ export interface DevConfig {
96
+ }
97
+
98
+ export interface Params {
99
+ pulseWidth: number;
100
+ pulse: string;
101
+ init: number;
102
+ sledOnline: string;
103
+ version: number;
104
+ timers: any[];
105
+ controlType: string;
106
+ partnerApikey: string;
107
+ bindInfos: BindInfos;
108
+ rssi: number;
109
+ staMac: string;
110
+ startup: string;
111
+ fwVersion: string;
112
+ switch: string;
113
+ }
114
+
115
+ export interface BindInfos {
116
+ gaction: string[];
117
+ }
118
+
119
+ export interface Settings {
120
+ alarmNotify: number;
121
+ opsHistory: number;
122
+ opsNotify: number;
123
+ }
124
+
125
+ export interface Tags {
126
+ m_4434_sany: string;
127
+ }
128
+
129
+ export interface Extra2 {
130
+ _id: string;
131
+ extra: Extra;
132
+ }
133
+
134
+ export interface Extra {
135
+ description: string;
136
+ brandId: string;
137
+ apmac: string;
138
+ mac: string;
139
+ ui: string;
140
+ modelInfo: string;
141
+ model: string;
142
+ manufacturer: string;
143
+ uiid: number;
144
+ staMac: string;
145
+ chipid: string;
146
+ }
147
+
148
+ export interface DeviceState {
149
+ status?: string;
150
+ state?: string;
151
+ error?: number;
152
+ msg?: string;
153
+ }
154
+
155
+ export interface SwitchCount {
156
+ status?: string;
157
+ switchesAmount?: number;
158
+ error?: number;
159
+ msg?: string;
160
+ }
161
+
162
+ export interface TemperatureHumidity {
163
+ status?: string;
164
+ temperature?: number;
165
+ humidity?: number;
166
+ error?: number;
167
+ msg?: string;
168
+ }
169
+
170
+ export interface PowerUsage {
171
+ status?: string;
172
+ monthly?: number;
173
+ daily?: Daily[];
174
+ error?: number;
175
+ msg?: string;
176
+ }
177
+
178
+ export interface FirmwareVersion {
179
+ status?: string;
180
+ fwVersion?: string;
181
+ error?: number;
182
+ msg?: string;
183
+ }
184
+
185
+ export interface LoginInfo {
186
+ at: string;
187
+ rt: string;
188
+ user: User;
189
+ region: string;
190
+ }
191
+
192
+ export interface User {
193
+ _id: string;
194
+ email: string;
195
+ appId: string;
196
+ lang: string;
197
+ online: boolean;
198
+ onlineTime: string;
199
+ ip: string;
200
+ location: string;
201
+ offlineTime: string;
202
+ userStatus: string;
203
+ appInfos: AppInfo[];
204
+ isAccepEmailAd: boolean;
205
+ bindInfos: LoginBindInfos;
206
+ createdAt: string;
207
+ apikey: string;
208
+ }
209
+
210
+ export interface LoginBindInfos {
211
+ gaction: string[];
212
+ }
213
+
214
+ export interface AppInfo {
215
+ appVersion: string;
216
+ os: string;
217
+ }
218
+
219
+ export interface Daily {
220
+ day: number;
221
+ usage: number;
222
+ }
223
+ }
package/main.js ADDED
@@ -0,0 +1,114 @@
1
+ const {
2
+ APP_ID: DEFAULT_APP_ID,
3
+ APP_SECRET: DEFAULT_APP_SECRET,
4
+ } = require('./src/data/constants');
5
+
6
+ const mixins = require('./src/mixins');
7
+ const errors = require('./src/data/errors');
8
+
9
+ class eWeLink {
10
+ constructor(parameters = {}) {
11
+ const {
12
+ region = 'us',
13
+ email = null,
14
+ phoneNumber = null,
15
+ password = null,
16
+ at = null,
17
+ apiKey = null,
18
+ devicesCache = null,
19
+ arpTable = null,
20
+ APP_ID = DEFAULT_APP_ID,
21
+ APP_SECRET = DEFAULT_APP_SECRET,
22
+ } = parameters;
23
+
24
+ const check = this.checkLoginParameters({
25
+ region,
26
+ email,
27
+ phoneNumber,
28
+ password,
29
+ at,
30
+ apiKey,
31
+ devicesCache,
32
+ arpTable,
33
+ });
34
+
35
+ if (check === false) {
36
+ throw new Error(errors.invalidCredentials);
37
+ }
38
+
39
+ this.region = region;
40
+ this.phoneNumber = phoneNumber;
41
+ this.email = email;
42
+ this.password = password;
43
+ this.at = at;
44
+ this.apiKey = apiKey;
45
+ this.devicesCache = devicesCache;
46
+ this.arpTable = arpTable;
47
+
48
+ this.APP_ID = APP_ID;
49
+ this.APP_SECRET = APP_SECRET;
50
+ }
51
+
52
+ // eslint-disable-next-line class-methods-use-this
53
+ checkLoginParameters(params) {
54
+ const { email, phoneNumber, password, devicesCache, arpTable, at } = params;
55
+
56
+ if (email !== null && phoneNumber !== null) {
57
+ return false;
58
+ }
59
+
60
+ if (
61
+ (email !== null && password !== null) ||
62
+ (phoneNumber !== null && password !== null) ||
63
+ (devicesCache !== null && arpTable !== null) ||
64
+ at !== null
65
+ ) {
66
+ return true;
67
+ }
68
+
69
+ return false;
70
+ }
71
+
72
+ /**
73
+ * Generate eWeLink API URL
74
+ *
75
+ * @returns {string}
76
+ */
77
+ getApiUrl() {
78
+ return `https://${this.region}-api.coolkit.cc:8080/api`;
79
+ }
80
+
81
+ /**
82
+ * Generate eWeLink OTA API URL
83
+ * @returns {string}
84
+ */
85
+ getOtaUrl() {
86
+ return `https://${this.region}-ota.coolkit.cc:8080/otaother`;
87
+ }
88
+
89
+ /**
90
+ * Generate eWeLink WebSocket URL
91
+ *
92
+ * @returns {string}
93
+ */
94
+ getApiWebSocket() {
95
+ return `wss://${this.region}-pconnect3.coolkit.cc:8080/api/ws`;
96
+ }
97
+
98
+ /**
99
+ * Generate Zeroconf URL
100
+ * @param device
101
+ * @returns {string}
102
+ */
103
+ getZeroconfUrl(device) {
104
+ const ip = this.getDeviceIP(device);
105
+ if (!ip) {
106
+ return null;
107
+ }
108
+ return `http://${ip}:8081/zeroconf`;
109
+ }
110
+ }
111
+
112
+ Object.assign(eWeLink.prototype, mixins);
113
+
114
+ module.exports = eWeLink;
package/package.json ADDED
@@ -0,0 +1,67 @@
1
+ {
2
+ "name": "@pipechela/ewelink-api",
3
+ "version": "1.0.0",
4
+ "description": "eWeLink API for Node.js (Fork by pipechela)",
5
+ "author": "pipechela",
6
+ "license": "MIT",
7
+ "typings": "./index.d.ts",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "git+https://github.com/pipechela/ewelink-api.git"
11
+ },
12
+ "bugs": {
13
+ "url": "https://github.com/pipechela/ewelink-api/issues"
14
+ },
15
+ "keywords": [
16
+ "ewelink",
17
+ "sonoff",
18
+ "api",
19
+ "node",
20
+ "nodejs"
21
+ ],
22
+ "main": "main.js",
23
+ "scripts": {
24
+ "test": "jest --runInBand --verbose",
25
+ "coverage": "jest --runInBand --verbose --coverage --coverageDirectory=coverage/jest",
26
+ "lint": "eslint .",
27
+ "lint:fix": "eslint . --fix"
28
+ },
29
+ "jest": {
30
+ "setupFilesAfterEnv": [
31
+ "<rootDir>/test/_setup/setupTests.js"
32
+ ],
33
+ "testPathIgnorePatterns": [
34
+ "/node_modules/",
35
+ ".cache"
36
+ ],
37
+ "coverageReporters": [
38
+ "text",
39
+ "html"
40
+ ]
41
+ },
42
+ "dependencies": {
43
+ "arpping": "github:skydiver/arpping",
44
+ "crypto-js": "^4.0.0",
45
+ "delay": "^4.4.0",
46
+ "node-fetch": "^2.6.1",
47
+ "random": "^2.2.0",
48
+ "websocket": "^1.0.32",
49
+ "websocket-as-promised": "^1.0.1"
50
+ },
51
+ "devDependencies": {
52
+ "babel-eslint": "^10.1.0",
53
+ "eslint": "^7.11.0",
54
+ "eslint-config-airbnb": "^18.2.0",
55
+ "eslint-config-prettier": "^6.12.0",
56
+ "eslint-config-wesbos": "0.0.19",
57
+ "eslint-plugin-html": "^6.1.0",
58
+ "eslint-plugin-import": "^2.22.1",
59
+ "eslint-plugin-jsx-a11y": "^6.3.1",
60
+ "eslint-plugin-prettier": "^3.1.4",
61
+ "eslint-plugin-react": "^7.21.4",
62
+ "eslint-plugin-react-hooks": "^4.1.2",
63
+ "jest": "^26.5.3",
64
+ "nock": "^12.0.3",
65
+ "prettier": "^1.19.1"
66
+ }
67
+ }
@@ -0,0 +1,34 @@
1
+ const fetch = require('node-fetch');
2
+
3
+ const WebSocket = require('./WebSocket');
4
+ const zeroConfUpdatePayload = require('../payloads/zeroConfUpdatePayload');
5
+ const { _get } = require('../helpers/utilities');
6
+
7
+ class ChangeStateZeroconf extends WebSocket {
8
+ static async set({ url, device, params, switches, state }) {
9
+ const selfApikey = device.apikey;
10
+ const deviceId = device.deviceid;
11
+ const deviceKey = device.devicekey;
12
+
13
+ const endpoint = switches ? 'switches' : 'switch';
14
+
15
+ const body = zeroConfUpdatePayload(selfApikey, deviceId, deviceKey, params);
16
+
17
+ const request = await fetch(`${url}/${endpoint}`, {
18
+ method: 'post',
19
+ body: JSON.stringify(body),
20
+ });
21
+
22
+ const response = await request.json();
23
+
24
+ const error = _get(response, 'error', false);
25
+
26
+ if (error === 403) {
27
+ return { error, msg: response.reason };
28
+ }
29
+
30
+ return { status: 'ok', state };
31
+ }
32
+ }
33
+
34
+ module.exports = ChangeStateZeroconf;
@@ -0,0 +1,58 @@
1
+ const WebSocket = require('./WebSocket');
2
+ const wssLoginPayload = require('../payloads/wssLoginPayload');
3
+ const wssUpdatePayload = require('../payloads/wssUpdatePayload');
4
+ const { _get } = require('../helpers/utilities');
5
+ const errors = require('../data/errors');
6
+
7
+ class DevicePowerUsageRaw extends WebSocket {
8
+ /**
9
+ * Get specific device power usage (raw data)
10
+ *
11
+ * @param apiUrl
12
+ * @param at
13
+ * @param apiKey
14
+ * @param deviceId
15
+ * @returns {Promise<{error: string}|{data: {hundredDaysKwhData: *}, status: string}|{msg: any, error: *}|{msg: string, error: number}>}
16
+ */
17
+ static async get({ apiUrl, at, apiKey, deviceId }) {
18
+ const payloadLogin = wssLoginPayload({ at, apiKey, appid: this.APP_ID });
19
+
20
+ const payloadUpdate = wssUpdatePayload({
21
+ apiKey,
22
+ deviceId,
23
+ params: { hundredDaysKwh: 'get' },
24
+ });
25
+
26
+ const response = await this.WebSocketRequest(apiUrl, [
27
+ payloadLogin,
28
+ payloadUpdate,
29
+ ]);
30
+
31
+ if (response.length === 1) {
32
+ return { error: errors.noPower };
33
+ }
34
+
35
+ const error = _get(response[1], 'error', false);
36
+
37
+ if (error === 403) {
38
+ return { error, msg: response[1].reason };
39
+ }
40
+
41
+ const hundredDaysKwhData = _get(
42
+ response[1],
43
+ 'config.hundredDaysKwhData',
44
+ false
45
+ );
46
+
47
+ if (!hundredDaysKwhData) {
48
+ return { error: errors.noPower };
49
+ }
50
+
51
+ return {
52
+ status: 'ok',
53
+ data: { hundredDaysKwhData },
54
+ };
55
+ }
56
+ }
57
+
58
+ module.exports = DevicePowerUsageRaw;
@@ -0,0 +1,57 @@
1
+ const W3CWebSocket = require('websocket').w3cwebsocket;
2
+ const WebSocketAsPromised = require('websocket-as-promised');
3
+ const delay = require('delay');
4
+
5
+ const errors = require('../data/errors');
6
+
7
+ class WebSocket {
8
+ /**
9
+ * Open WebSocket connection and send provided payloads
10
+ *
11
+ * @param url
12
+ * @param payloads
13
+ * @param delayTime
14
+ *
15
+ * @returns {Array}
16
+ */
17
+ static async WebSocketRequest(url, payloads, ...{ delayTime = 1000 }) {
18
+ const wsp = new WebSocketAsPromised(url, {
19
+ createWebSocket: wss => new W3CWebSocket(wss),
20
+ });
21
+
22
+ const responses = [];
23
+ wsp.onMessage.addListener(message => responses.push(JSON.parse(message)));
24
+
25
+ try {
26
+ await wsp.open();
27
+
28
+ for (const payload of payloads) {
29
+ await wsp.send(payload);
30
+ await delay(delayTime);
31
+ }
32
+
33
+ await wsp.close();
34
+ } catch (e) {
35
+ return this.customThrowError(e);
36
+ }
37
+
38
+ return responses;
39
+ }
40
+
41
+ /**
42
+ * Parse WebSocket errors and return user friendly messages
43
+ *
44
+ * @param e
45
+ *
46
+ * @returns {{error: string}|{msg: string, error: number}}
47
+ */
48
+ static customThrowError(e) {
49
+ const loginError = e.message.indexOf('WebSocket is not opened');
50
+ if (loginError > -1) {
51
+ return { error: 406, msg: errors['406'] };
52
+ }
53
+ return { error: errors.unknown };
54
+ }
55
+ }
56
+
57
+ module.exports = WebSocket;
@@ -0,0 +1,91 @@
1
+ const fs = require('fs');
2
+ const arpping = require('arpping')({});
3
+
4
+ class Zeroconf {
5
+ /**
6
+ * Build the ARP table
7
+ * @param ip
8
+ * @returns {Promise<unknown>}
9
+ */
10
+ static getArpTable(ip = null) {
11
+ return new Promise((resolve, reject) => {
12
+ arpping.discover(ip, (err, hosts) => {
13
+ if (err) {
14
+ return reject(err);
15
+ }
16
+ const arpTable = Zeroconf.fixMacAddresses(hosts);
17
+ return resolve(arpTable);
18
+ });
19
+ });
20
+ }
21
+
22
+ /**
23
+ * Sometime arp command returns mac addresses without leading zeroes.
24
+ * @param hosts
25
+ */
26
+ static fixMacAddresses(hosts) {
27
+ return hosts.map(host => {
28
+ const octets = host.mac.split(/[:\-]/);
29
+
30
+ const fixedMac = octets.map(octet => {
31
+ if (octet.length === 1) {
32
+ return `0${octet}`;
33
+ }
34
+ return octet;
35
+ });
36
+
37
+ return {
38
+ ip: host.ip,
39
+ mac: fixedMac.join(':'),
40
+ };
41
+ });
42
+ }
43
+
44
+ /**
45
+ * Save ARP table to local file
46
+ * @param config
47
+ * @returns {Promise<{error: string}|{file: {request: string; resolved: string} | any | string | string, status: string}>}
48
+ */
49
+ static async saveArpTable(config = {}) {
50
+ const ip = config.ip || null;
51
+ const fileName = config.file || './arp-table.json';
52
+ try {
53
+ const arpTable = await Zeroconf.getArpTable(ip);
54
+ const jsonContent = JSON.stringify(arpTable, null, 2);
55
+ fs.writeFileSync(fileName, jsonContent, 'utf8');
56
+ return { status: 'ok', file: fileName };
57
+ } catch (e) {
58
+ return { error: e.toString() };
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Read ARP table file
64
+ * @param fileName
65
+ * @returns {Promise<{error: string}|any>}
66
+ */
67
+ static async loadArpTable(fileName = './arp-table.json') {
68
+ try {
69
+ const jsonContent = await fs.readFileSync(fileName);
70
+ return JSON.parse(jsonContent);
71
+ } catch (e) {
72
+ return { error: e.toString() };
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Read devices cache file
78
+ * @param fileName
79
+ * @returns {Promise<{error: string}>}
80
+ */
81
+ static async loadCachedDevices(fileName = './devices-cache.json') {
82
+ try {
83
+ const jsonContent = await fs.readFileSync(fileName);
84
+ return JSON.parse(jsonContent);
85
+ } catch (e) {
86
+ return { error: e.toString() };
87
+ }
88
+ }
89
+ }
90
+
91
+ module.exports = Zeroconf;
@@ -0,0 +1,7 @@
1
+ const APP_ID = 'YzfeftUVcZ6twZw1OoVKPRFYTrGEg01Q';
2
+ const APP_SECRET = '4G91qSoboqYO4Y0XJ0LPPKIsq8reHdfa';
3
+
4
+ module.exports = {
5
+ APP_ID,
6
+ APP_SECRET,
7
+ };