homebridge-easy-mqtt 1.5.0-beta.0 → 1.5.0-beta.2
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 +1 -1
- package/README.md +2 -0
- package/dist/accessory/abstract/common.js +1 -1
- package/dist/accessory/abstract/common.js.map +1 -1
- package/dist/homebridge-ui/public/index.html +1 -1
- package/dist/model/mqtt.js +1 -1
- package/dist/model/mqtt.js.map +1 -1
- package/lib/fakegato-history/fakegato-history.js +887 -0
- package/lib/fakegato-history/fakegato-storage.js +178 -0
- package/lib/fakegato-history/fakegato-timer.js +133 -0
- package/lib/fakegato-history/lib/uuid.js +25 -0
- package/lib/fakegato-history/package.json +5 -0
- package/package.json +2 -2
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/*jshint esversion: 6,node: true,-W041: false */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const DEBUG = true;
|
|
5
|
+
|
|
6
|
+
var fs = require('fs');
|
|
7
|
+
var os = require('os');
|
|
8
|
+
var path = require('path');
|
|
9
|
+
var hostname = os.hostname().split(".")[0];
|
|
10
|
+
|
|
11
|
+
// Not needed for homebridge-easy-mqtt
|
|
12
|
+
// var googleDrive = require('./lib/googleDrive').drive;
|
|
13
|
+
|
|
14
|
+
var fileSuffix = '_persist.json';
|
|
15
|
+
|
|
16
|
+
var thisStorage;
|
|
17
|
+
|
|
18
|
+
class FakeGatoStorage {
|
|
19
|
+
constructor(params) {
|
|
20
|
+
if (!params)
|
|
21
|
+
params = {};
|
|
22
|
+
|
|
23
|
+
this.writers = [];
|
|
24
|
+
|
|
25
|
+
this.log = params.log || {};
|
|
26
|
+
if (!this.log.debug) {
|
|
27
|
+
this.log.debug = DEBUG ? console.log : function () { };
|
|
28
|
+
}
|
|
29
|
+
thisStorage = this;
|
|
30
|
+
this.addingWriter = false;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
addWriter(service, params) {
|
|
34
|
+
if (!this.addingWriter) {
|
|
35
|
+
this.addingWriter = true;
|
|
36
|
+
if (!params)
|
|
37
|
+
params = {};
|
|
38
|
+
|
|
39
|
+
this.log.debug("** Fakegato-storage AddWriter :", service.accessoryName);
|
|
40
|
+
|
|
41
|
+
let newWriter = {
|
|
42
|
+
'service': service,
|
|
43
|
+
'callback': params.callback,
|
|
44
|
+
'storage': params.storage || 'fs',
|
|
45
|
+
'fileName': params.filename || hostname + "_" + service.accessoryName + fileSuffix // Unique filename per homebridge server. Allows test environments on other servers not to break prod.
|
|
46
|
+
};
|
|
47
|
+
var onReady = typeof (params.onReady) == 'function' ? params.onReady : function () { }.bind(this);
|
|
48
|
+
|
|
49
|
+
switch (newWriter.storage) {
|
|
50
|
+
case 'fs':
|
|
51
|
+
newWriter.storageHandler = fs;
|
|
52
|
+
newWriter.path = params.path || path.join(os.homedir(), '.homebridge');
|
|
53
|
+
this.writers.push(newWriter);
|
|
54
|
+
this.addingWriter = false;
|
|
55
|
+
onReady();
|
|
56
|
+
break;
|
|
57
|
+
// Not needed for homebridge-easy-mqtt
|
|
58
|
+
// case 'googleDrive':
|
|
59
|
+
// newWriter.path = params.path || 'fakegato';
|
|
60
|
+
// newWriter.keyPath = params.keyPath || path.join(os.homedir(), '.homebridge');
|
|
61
|
+
// newWriter.storageHandler = new googleDrive({
|
|
62
|
+
// keyPath: newWriter.keyPath, callback: function () {
|
|
63
|
+
// this.addingWriter = false;
|
|
64
|
+
// onReady(arguments);
|
|
65
|
+
// }.bind(this), folder: newWriter.path
|
|
66
|
+
// });
|
|
67
|
+
// this.writers.push(newWriter);
|
|
68
|
+
// break;
|
|
69
|
+
/*
|
|
70
|
+
case 'memcached' :
|
|
71
|
+
|
|
72
|
+
break;
|
|
73
|
+
*/
|
|
74
|
+
}
|
|
75
|
+
} else {
|
|
76
|
+
setTimeout(function () {
|
|
77
|
+
this.addWriter(service, params);
|
|
78
|
+
}.bind(this), 100);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
getWriter(service) {
|
|
82
|
+
let findServ = function (element) {
|
|
83
|
+
return element.service === service;
|
|
84
|
+
};
|
|
85
|
+
return this.writers.find(findServ);
|
|
86
|
+
}
|
|
87
|
+
_getWriterIndex(service) {
|
|
88
|
+
let findServ = function (element) {
|
|
89
|
+
return element.service === service;
|
|
90
|
+
};
|
|
91
|
+
return this.writers.findIndex(findServ);
|
|
92
|
+
}
|
|
93
|
+
getWriters() {
|
|
94
|
+
return this.writers;
|
|
95
|
+
}
|
|
96
|
+
delWriter(service) {
|
|
97
|
+
let index = this._getWriterIndex(service);
|
|
98
|
+
this.writers.splice(index, 1);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
write(params) { // must be asynchronous
|
|
102
|
+
if (!this.writing) {
|
|
103
|
+
this.writing = true;
|
|
104
|
+
let writer = this.getWriter(params.service);
|
|
105
|
+
let callBack = typeof (params.callback) == 'function' ? params.callback : (typeof (writer.callback) == 'function' ? writer.callback : function () { }); // use parameter callback or writer callback or empty function
|
|
106
|
+
switch (writer.storage) {
|
|
107
|
+
case 'fs':
|
|
108
|
+
this.log.debug("** Fakegato-storage write FS file:", path.join(writer.path, writer.fileName), params.data.substr(1, 80));
|
|
109
|
+
writer.storageHandler.writeFile(path.join(writer.path, writer.fileName), params.data, 'utf8', function () {
|
|
110
|
+
this.writing = false;
|
|
111
|
+
callBack(arguments);
|
|
112
|
+
}.bind(this));
|
|
113
|
+
break;
|
|
114
|
+
// Not needed for homebridge-easy-mqtt
|
|
115
|
+
// case 'googleDrive':
|
|
116
|
+
// this.log.debug("** Fakegato-storage write googleDrive file:", writer.path, writer.fileName, params.data.substr(1, 80));
|
|
117
|
+
// writer.storageHandler.writeFile(writer.path, writer.fileName, params.data, function () {
|
|
118
|
+
// this.writing = false;
|
|
119
|
+
// callBack(arguments);
|
|
120
|
+
// }.bind(this));
|
|
121
|
+
// break;
|
|
122
|
+
/*
|
|
123
|
+
case 'memcached' :
|
|
124
|
+
|
|
125
|
+
break;
|
|
126
|
+
*/
|
|
127
|
+
}
|
|
128
|
+
} else {
|
|
129
|
+
setTimeout(function () { // retry in 100ms
|
|
130
|
+
this.write(params);
|
|
131
|
+
}.bind(this), 100);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
read(params) {
|
|
135
|
+
let writer = this.getWriter(params.service);
|
|
136
|
+
let callBack = typeof (params.callback) == 'function' ? params.callback : (typeof (writer.callback) == 'function' ? writer.callback : function () { }); // use parameter callback or writer callback or empty function
|
|
137
|
+
switch (writer.storage) {
|
|
138
|
+
case 'fs':
|
|
139
|
+
this.log.debug("** Fakegato-storage read FS file:", path.join(writer.path, writer.fileName));
|
|
140
|
+
writer.storageHandler.readFile(path.join(writer.path, writer.fileName), 'utf8', callBack);
|
|
141
|
+
break;
|
|
142
|
+
// Not needed for homebridge-easy-mqtt
|
|
143
|
+
// case 'googleDrive':
|
|
144
|
+
// this.log.debug("** Fakegato-storage read googleDrive file: %s/%s", writer.path, writer.fileName);
|
|
145
|
+
// writer.storageHandler.readFile(writer.path, writer.fileName, callBack);
|
|
146
|
+
// break;
|
|
147
|
+
/*
|
|
148
|
+
case 'memcached' :
|
|
149
|
+
|
|
150
|
+
break;
|
|
151
|
+
*/
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
remove(params) {
|
|
155
|
+
let writer = this.getWriter(params.service);
|
|
156
|
+
let callBack = typeof (params.callback) == 'function' ? params.callback : (typeof (writer.callback) == 'function' ? writer.callback : function () { }); // use parameter callback or writer callback or empty function
|
|
157
|
+
switch (writer.storage) {
|
|
158
|
+
case 'fs':
|
|
159
|
+
this.log.debug("** Fakegato-storage delete FS file:", path.join(writer.path, writer.fileName));
|
|
160
|
+
writer.storageHandler.unlink(path.join(writer.path, writer.fileName), callBack);
|
|
161
|
+
break;
|
|
162
|
+
// Not needed for homebridge-easy-mqtt
|
|
163
|
+
// case 'googleDrive':
|
|
164
|
+
// this.log.debug("** Fakegato-storage delete googleDrive file:", writer.path, writer.fileName);
|
|
165
|
+
// writer.storageHandler.deleteFile(writer.path, writer.fileName, callBack);
|
|
166
|
+
// break;
|
|
167
|
+
/*
|
|
168
|
+
case 'memcached' :
|
|
169
|
+
|
|
170
|
+
break;
|
|
171
|
+
*/
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
module.exports = {
|
|
177
|
+
FakeGatoStorage: FakeGatoStorage
|
|
178
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/*jshint esversion: 6,node: true,-W041: false */
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const DEBUG = true;
|
|
5
|
+
|
|
6
|
+
class FakeGatoTimer {
|
|
7
|
+
constructor(params) {
|
|
8
|
+
if (!params)
|
|
9
|
+
params = {};
|
|
10
|
+
this.subscribedServices = [];
|
|
11
|
+
this.minutes = params.minutes || 10;
|
|
12
|
+
|
|
13
|
+
this.intervalID = null;
|
|
14
|
+
this.running = false;
|
|
15
|
+
this.log = params.log || {};
|
|
16
|
+
if (!this.log.debug) {
|
|
17
|
+
this.log.debug = DEBUG ? console.log : function () { };
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Subscription management
|
|
22
|
+
subscribe(service, callback) {
|
|
23
|
+
this.log.debug("** Fakegato-timer Subscription :", service.accessoryName);
|
|
24
|
+
let newService = {
|
|
25
|
+
'service': service,
|
|
26
|
+
'callback': callback,
|
|
27
|
+
'backLog': [],
|
|
28
|
+
'previousBackLog': [],
|
|
29
|
+
'previousAvrg': {}
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
this.subscribedServices.push(newService);
|
|
33
|
+
}
|
|
34
|
+
getSubscriber(service) {
|
|
35
|
+
let findServ = function (element) {
|
|
36
|
+
return element.service === service;
|
|
37
|
+
};
|
|
38
|
+
return this.subscribedServices.find(findServ);
|
|
39
|
+
}
|
|
40
|
+
_getSubscriberIndex(service) {
|
|
41
|
+
let findServ = function (element) {
|
|
42
|
+
return element.service === service;
|
|
43
|
+
};
|
|
44
|
+
return this.subscribedServices.findIndex(findServ);
|
|
45
|
+
}
|
|
46
|
+
getSubscribers() {
|
|
47
|
+
return this.subscribedServices;
|
|
48
|
+
}
|
|
49
|
+
unsubscribe(service) {
|
|
50
|
+
let index = this._getSubscriberIndex(service);
|
|
51
|
+
this.subscribedServices.splice(index, 1);
|
|
52
|
+
if (this.subscribedServices.length === 0 && this.running)
|
|
53
|
+
this.stop();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Timer management
|
|
57
|
+
start() {
|
|
58
|
+
this.log.debug("**Start Global Fakegato-Timer - " + this.minutes + "min**");
|
|
59
|
+
if (this.running)
|
|
60
|
+
this.stop();
|
|
61
|
+
this.running = true;
|
|
62
|
+
this.intervalID = setInterval(this.executeCallbacks.bind(this), this.minutes * 60 * 1000);
|
|
63
|
+
}
|
|
64
|
+
stop() {
|
|
65
|
+
this.log.debug("**Stop Global Fakegato-Timer****");
|
|
66
|
+
clearInterval(this.intervalID);
|
|
67
|
+
this.running = false;
|
|
68
|
+
this.intervalID = null;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Data management
|
|
72
|
+
executeCallbacks() {
|
|
73
|
+
this.log.debug("**Fakegato-timer: executeCallbacks**");
|
|
74
|
+
if (this.subscribedServices.length !== 0) {
|
|
75
|
+
for (let s in this.subscribedServices) {
|
|
76
|
+
if (this.subscribedServices.hasOwnProperty(s)) {
|
|
77
|
+
|
|
78
|
+
let service = this.subscribedServices[s];
|
|
79
|
+
if (typeof (service.callback) == 'function') {
|
|
80
|
+
service.previousAvrg = service.callback({
|
|
81
|
+
'backLog': service.backLog,
|
|
82
|
+
'previousAvrg': service.previousAvrg,
|
|
83
|
+
'timer': this,
|
|
84
|
+
'immediate': false
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
executeImmediateCallback(service) {
|
|
92
|
+
this.log.debug("**Fakegato-timer: executeImmediateCallback**");
|
|
93
|
+
|
|
94
|
+
if (typeof (service.callback) == 'function' && service.backLog.length)
|
|
95
|
+
service.callback({
|
|
96
|
+
'backLog': service.backLog,
|
|
97
|
+
'timer': this,
|
|
98
|
+
'immediate': true
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
addData(params) {
|
|
102
|
+
let data = params.entry;
|
|
103
|
+
let service = params.service;
|
|
104
|
+
let immediateCallback = params.immediateCallback || false;
|
|
105
|
+
|
|
106
|
+
this.log.debug("**Fakegato-timer: addData ", service.accessoryName, data, " immediate: ", immediateCallback);
|
|
107
|
+
|
|
108
|
+
if (immediateCallback) // door or motion -> replace
|
|
109
|
+
this.getSubscriber(service).backLog[0] = data;
|
|
110
|
+
else
|
|
111
|
+
this.getSubscriber(service).backLog.push(data);
|
|
112
|
+
|
|
113
|
+
if (immediateCallback) {
|
|
114
|
+
//setTimeout(this.executeImmediateCallback.bind(this), 0,service);
|
|
115
|
+
this.executeImmediateCallback(this.getSubscriber(service));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (this.running === false)
|
|
119
|
+
this.start();
|
|
120
|
+
}
|
|
121
|
+
emptyData(service) {
|
|
122
|
+
this.log.debug("**Fakegato-timer: emptyData **", service.accessoryName);
|
|
123
|
+
let source = this.getSubscriber(service);
|
|
124
|
+
|
|
125
|
+
if (source.backLog.length) source.previousBackLog = source.backLog;
|
|
126
|
+
source.backLog = [];
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
module.exports = {
|
|
132
|
+
FakeGatoTimer: FakeGatoTimer
|
|
133
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// https://github.com/homebridge/HAP-NodeJS/blob/master/src/lib/util/uuid.ts
|
|
2
|
+
|
|
3
|
+
const VALID_UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
4
|
+
|
|
5
|
+
function isValid(UUID) {
|
|
6
|
+
return VALID_UUID_REGEX.test(UUID);
|
|
7
|
+
}
|
|
8
|
+
const VALID_SHORT_REGEX = /^[0-9a-f]{1,8}$/i;
|
|
9
|
+
|
|
10
|
+
function toLongFormUUID(uuid, base = '-0000-1000-8000-0026BB765291') {
|
|
11
|
+
if (isValid(uuid)) return uuid.toUpperCase();
|
|
12
|
+
if (!VALID_SHORT_REGEX.test(uuid)) throw new TypeError('uuid was not a valid UUID or short form UUID');
|
|
13
|
+
if (!isValid('00000000' + base)) throw new TypeError('base was not a valid base UUID');
|
|
14
|
+
|
|
15
|
+
return (('00000000' + uuid).substr(-8) + base).toUpperCase();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function toShortFormUUID(uuid, base = '-0000-1000-8000-0026BB765291') {
|
|
19
|
+
uuid = toLongFormUUID(uuid, base);
|
|
20
|
+
return (uuid.substr(0, 8));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
exports.isValid = isValid;
|
|
24
|
+
exports.toLongFormUUID = toLongFormUUID;
|
|
25
|
+
exports.toShortFormUUID = toShortFormUUID;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"displayName": "Homebridge Easy MQTT",
|
|
5
5
|
"description": "Homebridge plugin for easy control of MQTT devices",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"version": "1.5.0-beta.
|
|
7
|
+
"version": "1.5.0-beta.2",
|
|
8
8
|
"homepage": "https://github.com/mpatfield/homebridge-easy-mqtt#readme",
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
},
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@homebridge/plugin-ui-utils": "^2.0.2",
|
|
43
|
-
"fakegato-history": "
|
|
43
|
+
"fakegato-history": "file:./lib/fakegato-history",
|
|
44
44
|
"homebridge-lib": "^7.1.6",
|
|
45
45
|
"lodash.merge": "^4.6.2",
|
|
46
46
|
"mqtt": "^5.7.0",
|