-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
108 lines (93 loc) · 3.48 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
'use strict';
const mqtt = require('mqtt');
const defaults = {
};
let Service, Characteristic, Formats;
module.exports = homebridge => {
Service = homebridge.hap.Service;
Characteristic = homebridge.hap.Characteristic;
Formats = homebridge.hap.Characteristic.Formats;
homebridge.registerAccessory('homebridge-simple-mqtt', 'simple-mqtt', Thing);
}
class Thing {
constructor(log, config) {
config = { ...defaults, ...config };
this.log = log;
log(config)
const client = mqtt.connect(config.mqtt.address)
client.on('connect', function () {
log('mqtt connected');
});
this.client = client;
this.services = [];
Object.keys(config.services).forEach(name => {
const serviceConfig = config.services[name];
const service = this.makeService(config.name, serviceConfig);
this.services.push(service);
});
}
getServices() {
return this.services;
}
makeService(name, serviceConfig) {
const client = this.client;
const log = this.log;
const service = new Service[serviceConfig.type](name);
const allCharNames = Array.from(new Set(Object.keys(serviceConfig.props || {}).concat(Object.keys(serviceConfig.topics || {}))));
allCharNames.forEach(charName => {
const char = service.getCharacteristic(Characteristic[charName])
if (serviceConfig.props && charName in serviceConfig.props) {
char.setProps(serviceConfig.props[charName]);
}
if (serviceConfig.topics && charName in serviceConfig.topics) {
const topicDefines = serviceConfig.topics[charName];
this.subscribeTopics(char, topicDefines);
client.on('message', this.processMessage.bind(this, char, topicDefines));
char.on('set', this.publishTopic.bind(this, char, topicDefines));
}
});
return service;
}
publishTopic(char, topicDefines, state, callback) {
const client = this.client;
const log = this.log;
client.publish(topicDefines.set, JSON.stringify({
value: state,
}));
log(char.displayName + ' set to ' + state);
callback(null);
}
processMessage(char, topicDefines, topic, message) {
const client = this.client;
const log = this.log;
const payload = JSON.parse(message);
if (topicDefines.get == topic) {
char.updateValue(payload.value);
log(char.displayName + ' value updated to ' + payload.value);
}
Object.keys(topicDefines.props || {}).forEach(propKey => {
if (topicDefines.props[propKey] == topic) {
char.setProps({
[propKey]: payload.value,
});
log(char.displayName + ' ' + propKey + ' updated to ' + payload.value);
}
});
}
subscribeTopics(char, topicDefines) {
const client = this.client;
const log = this.log;
client.subscribe(topicDefines.get, (err) => {
if (!err) {
log(topicDefines.get + ' subscribed');
}
});
Object.keys(topicDefines.props || []).forEach(propKey => {
client.subscribe(topicDefines.props[propKey], (err) => {
if (!err) {
log(topicDefines.props[propKey] + ' subscribed');
}
});
});
}
}