-
Notifications
You must be signed in to change notification settings - Fork 1
/
node_helper.js
240 lines (194 loc) · 7.2 KB
/
node_helper.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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/* eslint-disable curly */
/* eslint-disable prettier/prettier */
/* eslint-disable no-trailing-spaces */
/* Magic Mirror
* Node Helper: MMM-WeasleyClock
*
* By {{AUTHOR_NAME}}
* {{LICENSE}} Licensed.
*/
var NodeHelper = require("node_helper");
const mqtt = require("mqtt");
const fs = require("fs");
const {Howl, Howler} = require("howler");
var client;
module.exports = NodeHelper.create({
// Initialize MQTT connection object
start: function() {
},
stop: function() {
this.client.end();
this.client = null;
},
/* socketNotificationReceived(notification, payload)
* This method is called when a socket notification arrives.
*
* argument notification string - The identifier of the noitication.
* argument payload mixed - The payload of the notification.
*/
socketNotificationReceived: function(notification, payload) {
console.log("Weasley clock node helper received notifications: " + notification);
if(notification === "MMM-WeasleyClock-CONFIG") {
this.establishConnection(payload);
}
if (notification === "MMM-WeasleyClock-START") {
if (payload.debug) { console.log("Starting Weasley Clock message client. Notification:", notification, "payload: ", payload); }
// Send notification
this.sendNotificationTest(this.anotherFunction());
}
// save this for later. Perhaps provide long/lat regions for push to phones.
if (notification === "MMM-WeasleyClock-UPDATECLIENTS") {
if (payload.debug) { console.log("Updating clients."); }
// this.updateClients(payload);
}
// possibly this will never be used
if (notification === "MMM-WeasleyClock-PLAYSOUND") {
if (payload.debug) { console.log("Playing sound effect."); }
this.playSound(payload);
}
},
establishConnection: function(config) {
var subTopic1 = "owntracks/" + config.uniqueId + "/";
var options = {
"qos": 2,
"rap": true,
"rh": true,
}
console.debug ("Establishing connection.");
if (this.client == null) {
console.debug("Getting new client object");
this.client = this.getMQTTClient(config);
}
var client = this.client;
// connect and subscribe to Owntracks topics
client.on("connect", () => {
console.debug("Subscribing to all content for uniqueID");
client.subscribe(subTopic1 + "#", options, function(err, granted) {
if (err) {
console.error(err, "Error subscribing to topics.");
}
console.debug("Subscribed: " + JSON.stringify(granted));
});
});
// Handle published messages from Owntracks devices
client.on("message", (topic, message) => {
console.log ("message received in topic " + topic);
try {
var msgObj = JSON.parse(message.toString());
this.handleMessage(config, topic, msgObj);
} catch (e) {
console.error("Error processing message: " + message.toString());
}
});
client.on("error", function(error) {
console.error("Can't connect." + error);
process.exit(1);
});
},
/**
* Creates an MQTT client object configured for a connection.
* @param {Object} config The configuration object as modified by the user
*/
getMQTTClient: function(config) {
console.log("Establishing mqtt connection using uniqueId: " + config.uniqueId);
var userName = ((config.mirrorUser == null) ? config.uniqueId : config.mirrorUser );
var userPass = ((config.mirrorPass == null) ? "BogusPassword" : config.mirrorPass );
var protocol = ((config.disableEncryption) ? "mqtt://" : "mqtts://");
var options = {
clientId: "mirror-" + config.uniqueId,
username: userName,
password: userPass,
rejectUnauthorized: false,
host: config.host,
port: config.port,
clean: false
};
console.debug("Connecting with: " + JSON.stringify(options));
client = mqtt.connect(protocol + config.host, options);
return client;
},
// Process the messages received by the MQTT client
handleMessage: function(config, topic, message) {
if (config.debug) console.debug("Message from device: " + JSON.stringify(message));
if (message == null) {
console.error("Null value from MQTT server.");
}
// extract person from path
var topicArray = topic.split("/");
var person = topicArray[topicArray.length - 1];
if (config.debug) console.debug("Parsing message for '" + person + "'");
message.person = person;
// valid _type are: beacon, card, cmd, configuration, encrypted, location, lwt, steps, transition, waypoint, waypoints
if (config.debug) console.debug("processing message type: " + message._type);
switch (message._type) {
case "waypoint": console.debug("New Waypoint detected");
this.sendSocketNotification("MMM-WeasleyClock-WAYPOINT", message);
break;
case "location": console.debug("location detected");
this.processLocation(config, message);
break;
case "transition": console.debug("transition event detected.");
this.processTransition(config, message);
break;
case "lwt": console.debug("LWT event detected.");
// var options = { key : message.tid, location: "lost"};
// sendSocketNotification("MMM-WeasleyMirror-LOST", options);
this.sendSocketNotification("MMM-WeasleyClock-LOST", message);
break;
default: if (config.debug) console.debug("Event received but not processed.");
}
},
/**
* Processes the location messages. Looks for a high velocity and a location.
* Currently, location takes precedence over velocity, so if you're driving
* past a location, it will mark you as in that location instead of traveling.
* @param {*} config Configuration object passed in from the module.
* @param {*} message Message received from the MQTT server.
*/
processLocation: function(config, message) {
var vel = message.vel;
if (config.debug) console.debug("Traveling at " + vel);
// check for region
if (message.inregions) {
console.log(message.person + " is in region '" + message.inregions + "'");
this.sendSocketNotification("MMM-WeasleyClock-UPDATE", message);
} else if (vel > 10) {
console.log("Mark " + message.person + " as traveling");
this.sendSocketNotification("MMM-WeasleyClock-TRAVELING", message);
}
},
// Looks for module location match with transition message.
// Note: transition messages put regions in the "desc" field.
processTransition: function(config, message) {
var event = message.event;
if (event == "enter") {
if (config.debug) console.debug(message.person + " has entered region(s) '" + message.desc +"'");
message.inregions = new Array(message.desc);
this.sendSocketNotification("MMM-WeasleyClock-UPDATE", message);
} else {
if (config.debug) console.debug(message.person + " has just left '" + message.inregions + "'");
this.sendSocketNotification("MMM-WeasleyClock-TRAVELING", message);
}
//TODO: add notification noise to signal change in state.
},
playSound: function (config) {
var filename = "/sounds/crank-n-chimes.mp3";
let soundfile = this.path + filename;
// Make sure file exists before playing
try {
fs.accessSync(soundfile, fs.F_OK);
if (config.debug) console.debug("Playing " + soundfile);
var howl = new Howl(
{
src:[soundfile],
onend: function() {
if (config.debug) console.debug("Finished playback.");
}
});
} catch (e) {
// Custom sequence doesn't exist
console.error("Sound does not exist: " + soundfile);
return;
}
},
});