-
Notifications
You must be signed in to change notification settings - Fork 8
/
index.js
113 lines (100 loc) · 4.34 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env node
const MqttSmarthome = require("mqtt-smarthome-connect");
const Hs100Api = require('tplink-smarthome-api');
const log = require('yalm');
const shortid = require('shortid');
const Yatl = require('yetanothertimerlibrary');
const pkg = require('./package.json');
const config = require('yargs')
.env('HS100TOMQTT')
.usage(pkg.name + ' ' + pkg.version + '\n' + pkg.description + '\n\nUsage: $0 [options]')
.describe('verbosity', 'possible values: "error", "warn", "info", "debug"')
.describe('name', 'instance name. used as mqtt client id and as prefix for connected topic')
.describe('mqtt-url', 'mqtt broker url. See https://github.com/mqttjs/MQTT.js#connect-using-a-url')
.describe('polling-interval', 'polling interval (in ms) for status updates')
.describe('devices', 'list of device IPs as String, multiple IPs separated by space')
.alias({
h: 'help',
m: 'mqtt-url',
v: 'verbosity'
})
.default({
name: 'hs100',
'mqtt-url': 'mqtt://127.0.0.1',
'polling-interval': 3000
})
.version()
.help('help')
.argv;
const devices = [];
log.setLevel(config.verbosity);
log.info(pkg.name + ' ' + pkg.version + ' starting');
log.debug("loaded config: ", config);
if (typeof config.devices === 'string') {
config.devices.split(" ").forEach( (ip) => {
devices.push({"host":ip, "port":9999});
});
}
const deviceTimer = {};
log.info('mqtt trying to connect', config.mqttUrl);
const mqtt = new MqttSmarthome(config.mqttUrl, {
logger: log,
clientId: config.name + '_' + + shortid.generate(),
will: {topic: config.name + '/maintenance/_bridge/online', payload: 'false', retain: true}
});
mqtt.connect();
mqtt.on('connect', () => {
log.info('mqtt connected', config.mqttUrl);
mqtt.publish(config.name + '/maintenance/_bridge/online', true, {retain: true});
});
const client = new Hs100Api.Client({logLevel: config.verbosity, logger: log});
client.on('device-new', (device) => {
log.info('hs100 device-new', device.model, device.host, device.deviceId, device.name);
mqtt.publish(config.name + "/maintenance/" + device.deviceId + "/online", true);
mqtt.subscribe(config.name + "/set/" + device.deviceId, (topic, message, packet) => {
if (typeof message === 'object') {
if ('val' in message) {
if (typeof message.val === 'boolean') {
device.setPowerState(message.val);
}
}
}
if (typeof message === 'boolean') {
device.setPowerState(message);
}
deviceTimer[device.deviceId].exec();
});
deviceTimer[device.deviceId] = new Yatl.Timer(() => {
device.getInfo().then(info => {
let message = {};
message.val = info.sysInfo.relay_state === 1;
message.power = info.emeter.realtime.power;
message.voltage = info.emeter.realtime.voltage;
message.current = info.emeter.realtime.current;
message.energy = info.emeter.realtime.energy;
mqtt.publish(config.name + "/status/" + device.deviceId, message);
}).catch((err) => { // If time is set wrong on HS100 (e.g. because you blocked internet access for it) status updates may arrive as error
let message = {};
message.val = err.response.system.get_sysinfo.relay_state === 1;
message.power = err.response.emeter.get_realtime.power;
message.voltage = err.response.emeter.get_realtime.voltage;
message.current = err.response.emeter.get_realtime.current;
message.energy = err.response.emeter.get_realtime.energy;
mqtt.publish(config.name + "/status/" + device.deviceId, message);
});
}).start(config.pollingInterval);
});
client.on('device-online', (device) => {
log.debug('hs100 device-online callback', device.name);
mqtt.publish(config.name + "/maintenance/" + device.deviceId + "/online", true);
deviceTimer[device.deviceId].start(config.pollingInterval);
});
client.on('device-offline', (device) => {
log.warn('hs100 device-offline callback', device.name);
mqtt.publish(config.name + "/maintenance/" + device.deviceId + "/online", false);
deviceTimer[device.deviceId].stop();
});
log.info('Starting Device Discovery');
client.startDiscovery({
devices: devices
});