vrpc 3.0.3 → 3.1.1
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/browser/vrpc.js +1 -1
- package/package.json +1 -1
- package/vrpc/VrpcAdapter.js +165 -99
- package/vrpc/VrpcAgent.js +72 -56
- package/vrpc/VrpcClient.js +64 -12
- package/vrpc/VrpcNative.js +36 -4
- package/CHANGELOG.md +0 -774
package/package.json
CHANGED
package/vrpc/VrpcAdapter.js
CHANGED
|
@@ -350,9 +350,17 @@ class VrpcAdapter {
|
|
|
350
350
|
({ tag }) => tag === 'param' || tag === 'arg' || tag === 'argument'
|
|
351
351
|
)
|
|
352
352
|
if (params.length > 0) {
|
|
353
|
-
params = params.map(
|
|
354
|
-
|
|
355
|
-
|
|
353
|
+
params = params.map(
|
|
354
|
+
({
|
|
355
|
+
name,
|
|
356
|
+
optional,
|
|
357
|
+
description,
|
|
358
|
+
type,
|
|
359
|
+
default: defaultValue
|
|
360
|
+
}) => {
|
|
361
|
+
return { name, optional, description, type, defaultValue }
|
|
362
|
+
}
|
|
363
|
+
)
|
|
356
364
|
} else {
|
|
357
365
|
params = []
|
|
358
366
|
}
|
|
@@ -375,7 +383,8 @@ class VrpcAdapter {
|
|
|
375
383
|
name: 'instanceName',
|
|
376
384
|
optional: false,
|
|
377
385
|
description: 'Name of the instance to be created',
|
|
378
|
-
type: 'string'
|
|
386
|
+
type: 'string',
|
|
387
|
+
defaultValue: undefined
|
|
379
388
|
},
|
|
380
389
|
...params
|
|
381
390
|
]
|
|
@@ -390,7 +399,7 @@ class VrpcAdapter {
|
|
|
390
399
|
}
|
|
391
400
|
|
|
392
401
|
static _call (json) {
|
|
393
|
-
|
|
402
|
+
this._mustTrackClient = false // reset client tracking flag
|
|
394
403
|
switch (json.f) {
|
|
395
404
|
case '__createIsolated__':
|
|
396
405
|
VrpcAdapter._handleCreateIsolated(json)
|
|
@@ -408,10 +417,9 @@ class VrpcAdapter {
|
|
|
408
417
|
// this call may have the side-effect of taking a listener on board
|
|
409
418
|
VrpcAdapter._handleCall(json)
|
|
410
419
|
}
|
|
411
|
-
const after = Object.keys(VrpcAdapter._listeners).length
|
|
412
420
|
// if we took a listener on board we must tell our caller such that
|
|
413
421
|
// things can be cleaned up later.
|
|
414
|
-
return
|
|
422
|
+
return this._mustTrackClient
|
|
415
423
|
}
|
|
416
424
|
|
|
417
425
|
static _handleCreateIsolated (json) {
|
|
@@ -500,7 +508,8 @@ class VrpcAdapter {
|
|
|
500
508
|
}
|
|
501
509
|
|
|
502
510
|
static sanitizeEventListenerReturnValues (ret) {
|
|
503
|
-
return
|
|
511
|
+
return ret &&
|
|
512
|
+
typeof ret === 'object' &&
|
|
504
513
|
ret._events !== undefined &&
|
|
505
514
|
ret._eventsCount !== undefined
|
|
506
515
|
? true
|
|
@@ -593,13 +602,7 @@ class VrpcAdapter {
|
|
|
593
602
|
if (VrpcAdapter._isFunction(entry.removeAllListeners)) {
|
|
594
603
|
entry.removeAllListeners()
|
|
595
604
|
}
|
|
596
|
-
|
|
597
|
-
VrpcAdapter._listeners
|
|
598
|
-
)) {
|
|
599
|
-
if (instance === instanceId) {
|
|
600
|
-
VrpcAdapter._listeners[key] = { clients }
|
|
601
|
-
}
|
|
602
|
-
}
|
|
605
|
+
delete VrpcAdapter._listeners[instanceId]
|
|
603
606
|
VrpcAdapter._instances.delete(instanceId)
|
|
604
607
|
return true
|
|
605
608
|
}
|
|
@@ -607,18 +610,21 @@ class VrpcAdapter {
|
|
|
607
610
|
}
|
|
608
611
|
|
|
609
612
|
static _unregisterClient (clientId) {
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
VrpcAdapter.getInstance(
|
|
617
|
-
|
|
613
|
+
Object.entries(VrpcAdapter._listeners).forEach(([ik, iv]) => {
|
|
614
|
+
Object.entries(iv).forEach(([ek, ev]) => {
|
|
615
|
+
const { clients, listener, event } = ev
|
|
616
|
+
if (clients.has(clientId)) {
|
|
617
|
+
clients.delete(clientId)
|
|
618
|
+
if (clients.size === 0) {
|
|
619
|
+
const instance = VrpcAdapter.getInstance(ik)
|
|
620
|
+
if (instance && instance.removeListener) {
|
|
621
|
+
instance.removeListener(event, listener)
|
|
622
|
+
}
|
|
623
|
+
delete VrpcAdapter._listeners[ik][ek]
|
|
624
|
+
}
|
|
618
625
|
}
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
}
|
|
626
|
+
})
|
|
627
|
+
})
|
|
622
628
|
}
|
|
623
629
|
|
|
624
630
|
static _validate (schema, params) {
|
|
@@ -630,102 +636,162 @@ class VrpcAdapter {
|
|
|
630
636
|
}
|
|
631
637
|
|
|
632
638
|
static _unwrapArguments (json, instanceId) {
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
args = args.slice(1)
|
|
642
|
-
}
|
|
643
|
-
const unwrapped = instanceId ? [func] : []
|
|
639
|
+
const clientId = json.s
|
|
640
|
+
// if we came from a "callAll" we will have an instanceId defined
|
|
641
|
+
// things are different for callAll as we have to dispatch the instanceIds
|
|
642
|
+
const isCallAll = instanceId !== undefined
|
|
643
|
+
const context = isCallAll ? instanceId : json.c
|
|
644
|
+
const args = isCallAll ? json.a.slice(1) : json.a
|
|
645
|
+
const func = isCallAll ? json.a[0] : json.f
|
|
646
|
+
const unwrapped = isCallAll ? [func] : []
|
|
644
647
|
for (const arg of args) {
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
648
|
+
if (typeof arg === 'string') {
|
|
649
|
+
if (arg.startsWith('__f__')) {
|
|
650
|
+
// function callback
|
|
651
|
+
unwrapped.push(
|
|
652
|
+
this._generateCallback({
|
|
653
|
+
clientId,
|
|
654
|
+
isCallAll,
|
|
655
|
+
instanceId: context,
|
|
656
|
+
eventId: arg
|
|
657
|
+
})
|
|
658
|
+
)
|
|
659
|
+
} else if (arg.startsWith('__e__')) {
|
|
660
|
+
// event registration
|
|
661
|
+
if (func === 'on' || func === 'addListener') {
|
|
662
|
+
this._mustTrackClient = true
|
|
663
|
+
const listener = VrpcAdapter._registerListener({
|
|
664
|
+
clientId,
|
|
665
|
+
isCallAll,
|
|
666
|
+
instanceId: context,
|
|
667
|
+
eventId: arg,
|
|
668
|
+
event: args[0]
|
|
669
|
+
})
|
|
670
|
+
if (
|
|
671
|
+
VrpcAdapter.getInstance(context)
|
|
672
|
+
.listeners(arg)
|
|
673
|
+
.includes(listener)
|
|
674
|
+
) {
|
|
675
|
+
return null // skip call as listener is already registered
|
|
676
|
+
}
|
|
677
|
+
unwrapped.push(listener)
|
|
678
|
+
// event un-registration
|
|
679
|
+
} else if (func === 'off' || func === 'removeListener') {
|
|
680
|
+
const listener = VrpcAdapter._unregisterListener({
|
|
681
|
+
clientId,
|
|
682
|
+
instanceId: context,
|
|
683
|
+
eventId: arg
|
|
684
|
+
})
|
|
685
|
+
if (!listener) {
|
|
686
|
+
return null // skip call as others are still interested
|
|
687
|
+
}
|
|
688
|
+
unwrapped.push(listener)
|
|
689
|
+
} else {
|
|
690
|
+
this._mustTrackClient = true
|
|
691
|
+
const listener = VrpcAdapter._registerListener({
|
|
692
|
+
clientId,
|
|
693
|
+
isCallAll,
|
|
694
|
+
instanceId: context,
|
|
695
|
+
eventId: arg,
|
|
696
|
+
event: null
|
|
697
|
+
})
|
|
698
|
+
unwrapped.push(listener)
|
|
659
699
|
}
|
|
660
700
|
} else {
|
|
661
|
-
|
|
662
|
-
}
|
|
663
|
-
// see whether the requested listener is an EventEmitter registration
|
|
664
|
-
if (func === 'on' || func === 'addListener') {
|
|
665
|
-
// if this event is already registered on the given instance
|
|
666
|
-
// avoid a second registration
|
|
667
|
-
if (
|
|
668
|
-
VrpcAdapter._listeners[arg].event &&
|
|
669
|
-
VrpcAdapter._listeners[arg].instances.has(context)
|
|
670
|
-
) {
|
|
671
|
-
return null // means that this call won't be forwarded
|
|
672
|
-
}
|
|
673
|
-
VrpcAdapter._listeners[arg].event = args[0]
|
|
674
|
-
VrpcAdapter._listeners[arg].instances.add(context)
|
|
675
|
-
}
|
|
676
|
-
if (func === 'off' || func === 'removeListener') {
|
|
677
|
-
const {
|
|
678
|
-
clients,
|
|
679
|
-
instances,
|
|
680
|
-
listener,
|
|
681
|
-
event
|
|
682
|
-
} = VrpcAdapter._listeners[arg]
|
|
683
|
-
clients.delete(sender)
|
|
684
|
-
instances.delete(context)
|
|
685
|
-
if (clients.size === 0) {
|
|
686
|
-
delete VrpcAdapter._listeners[arg]
|
|
687
|
-
VrpcAdapter.getInstance(context).off(event, listener)
|
|
688
|
-
}
|
|
689
|
-
return null // means that this call won't be forwarded
|
|
701
|
+
unwrapped.push(arg)
|
|
690
702
|
}
|
|
691
703
|
} else {
|
|
692
|
-
//
|
|
704
|
+
// regular argument
|
|
693
705
|
unwrapped.push(arg)
|
|
694
706
|
}
|
|
695
707
|
}
|
|
696
708
|
return unwrapped
|
|
697
709
|
}
|
|
698
710
|
|
|
699
|
-
static
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
711
|
+
static _generateCallback ({ eventId, clientId, instanceId, isCallAll }) {
|
|
712
|
+
return (...innerArgs) => {
|
|
713
|
+
// "callAll" event notifications expect the instanceId as first argument
|
|
714
|
+
const a = isCallAll ? [instanceId, ...innerArgs] : [...innerArgs]
|
|
715
|
+
VrpcAdapter._callback({ a, s: clientId, i: eventId })
|
|
716
|
+
}
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
static _registerListener ({
|
|
720
|
+
eventId,
|
|
721
|
+
clientId,
|
|
722
|
+
instanceId,
|
|
723
|
+
event,
|
|
724
|
+
isCallAll
|
|
725
|
+
}) {
|
|
726
|
+
if (!VrpcAdapter._listeners[instanceId]) {
|
|
727
|
+
VrpcAdapter._listeners[instanceId] = {
|
|
728
|
+
[eventId]: {
|
|
729
|
+
event,
|
|
730
|
+
clients: new Set([clientId]),
|
|
731
|
+
listener: VrpcAdapter._generateListener({
|
|
732
|
+
eventId,
|
|
733
|
+
instanceId,
|
|
734
|
+
isCallAll
|
|
735
|
+
})
|
|
706
736
|
}
|
|
707
737
|
}
|
|
738
|
+
} else if (!VrpcAdapter._listeners[instanceId][eventId]) {
|
|
739
|
+
VrpcAdapter._listeners[instanceId][eventId] = {
|
|
740
|
+
event,
|
|
741
|
+
clients: new Set([clientId]),
|
|
742
|
+
listener: VrpcAdapter._generateListener({
|
|
743
|
+
eventId,
|
|
744
|
+
instanceId,
|
|
745
|
+
isCallAll
|
|
746
|
+
})
|
|
747
|
+
}
|
|
748
|
+
} else {
|
|
749
|
+
VrpcAdapter._listeners[instanceId][eventId].clients.add(clientId)
|
|
708
750
|
}
|
|
751
|
+
return VrpcAdapter._listeners[instanceId][eventId].listener
|
|
709
752
|
}
|
|
710
753
|
|
|
711
|
-
static
|
|
754
|
+
static _generateListener ({ eventId, instanceId, isCallAll }) {
|
|
712
755
|
return (...innerArgs) => {
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
VrpcAdapter._callback({ a, s: sender, i: id })
|
|
756
|
+
const a = isCallAll ? [instanceId, ...innerArgs] : [...innerArgs]
|
|
757
|
+
VrpcAdapter._callback({ a, i: eventId })
|
|
716
758
|
}
|
|
717
759
|
}
|
|
718
760
|
|
|
719
|
-
static
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
const
|
|
725
|
-
|
|
761
|
+
static _unregisterListener ({ eventId, clientId, instanceId }) {
|
|
762
|
+
if (
|
|
763
|
+
VrpcAdapter._listeners[instanceId] &&
|
|
764
|
+
VrpcAdapter._listeners[instanceId][eventId]
|
|
765
|
+
) {
|
|
766
|
+
const { listener, clients } = VrpcAdapter._listeners[instanceId][eventId]
|
|
767
|
+
clients.delete(clientId)
|
|
768
|
+
if (clients.size === 0) {
|
|
769
|
+
delete VrpcAdapter._listeners[instanceId][eventId]
|
|
770
|
+
if (Object.keys(VrpcAdapter._listeners[instanceId]).length === 0) {
|
|
771
|
+
delete VrpcAdapter._listeners[instanceId]
|
|
772
|
+
}
|
|
773
|
+
return listener
|
|
774
|
+
}
|
|
726
775
|
}
|
|
727
776
|
}
|
|
728
777
|
|
|
778
|
+
static _removeAllListeners (event, clientId, instanceId) {
|
|
779
|
+
const eventIds = VrpcAdapter._listeners[instanceId]
|
|
780
|
+
if (!eventIds) return
|
|
781
|
+
Object.entries(eventIds).forEach(([ek, ev]) => {
|
|
782
|
+
if (ev.event === event && ev.clients.has(clientId)) {
|
|
783
|
+
ev.clients.delete(clientId)
|
|
784
|
+
if (ev.clients.size === 0) {
|
|
785
|
+
VrpcAdapter.getInstance(instanceId).removeListener(
|
|
786
|
+
ev.event,
|
|
787
|
+
ev.listener
|
|
788
|
+
)
|
|
789
|
+
delete VrpcAdapter._listeners[instanceId][ek]
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
})
|
|
793
|
+
}
|
|
794
|
+
|
|
729
795
|
static _handlePromise (json, promise) {
|
|
730
796
|
try {
|
|
731
797
|
const cid = VrpcAdapter._correlationId++ % Number.MAX_SAFE_INTEGER
|
package/vrpc/VrpcAgent.js
CHANGED
|
@@ -92,7 +92,7 @@ class VrpcAgent extends EventEmitter {
|
|
|
92
92
|
*
|
|
93
93
|
* @constructor
|
|
94
94
|
* @param {Object} obj
|
|
95
|
-
* @param {String} [obj.username
|
|
95
|
+
* @param {String} [obj.username] MQTT username
|
|
96
96
|
* @param {String} [obj.password] MQTT password (if no token is provided)
|
|
97
97
|
* @param {String} [obj.token] Access token
|
|
98
98
|
* @param {String} [obj.domain='vrpc'] The domain under which the agent-provided code is reachable
|
|
@@ -101,6 +101,7 @@ class VrpcAgent extends EventEmitter {
|
|
|
101
101
|
* @param {Object} [obj.log=console] Log object (must support debug, info, warn, and error level)
|
|
102
102
|
* @param {String} [obj.bestEffort=false] If true, message will be sent with best effort, i.e. no caching if offline
|
|
103
103
|
* @param {String} [obj.version=''] The (user-defined) version of this agent
|
|
104
|
+
* @param {String} [obj.mqttClientId='<generated()>'] Explicitly set the mqtt client id.
|
|
104
105
|
*
|
|
105
106
|
* @example
|
|
106
107
|
* const agent = new Agent({
|
|
@@ -109,15 +110,16 @@ class VrpcAgent extends EventEmitter {
|
|
|
109
110
|
* })
|
|
110
111
|
*/
|
|
111
112
|
constructor ({
|
|
112
|
-
|
|
113
|
+
username,
|
|
113
114
|
password,
|
|
114
|
-
|
|
115
|
+
token,
|
|
115
116
|
domain = 'vrpc',
|
|
116
117
|
agent = VrpcAgent._generateAgentName(),
|
|
117
118
|
broker = 'mqtts://vrpc.io:8883',
|
|
118
119
|
log = 'console',
|
|
119
120
|
bestEffort = false,
|
|
120
|
-
version = ''
|
|
121
|
+
version = '',
|
|
122
|
+
mqttClientId = null
|
|
121
123
|
} = {}) {
|
|
122
124
|
super()
|
|
123
125
|
this._validateDomain(domain)
|
|
@@ -130,7 +132,13 @@ class VrpcAgent extends EventEmitter {
|
|
|
130
132
|
this._broker = broker
|
|
131
133
|
this._qos = bestEffort ? 0 : 1
|
|
132
134
|
this._version = version
|
|
133
|
-
this.
|
|
135
|
+
this._mqttClientId =
|
|
136
|
+
mqttClientId ||
|
|
137
|
+
`va3${crypto
|
|
138
|
+
.createHash('md5')
|
|
139
|
+
.update(this._domain + this._agent)
|
|
140
|
+
.digest('hex')
|
|
141
|
+
.substring(0, 20)}`
|
|
134
142
|
if (log === 'console') {
|
|
135
143
|
this._log = console
|
|
136
144
|
this._log.debug = () => {}
|
|
@@ -165,23 +173,21 @@ class VrpcAgent extends EventEmitter {
|
|
|
165
173
|
* rejects
|
|
166
174
|
*/
|
|
167
175
|
async serve () {
|
|
168
|
-
const md5 = crypto
|
|
169
|
-
.createHash('md5')
|
|
170
|
-
.update(this._domain + this._agent)
|
|
171
|
-
.digest('hex')
|
|
172
|
-
.substr(0, 20)
|
|
173
176
|
let username = this._username
|
|
174
177
|
let password = this._password
|
|
175
178
|
if (this._token) {
|
|
176
|
-
username =
|
|
179
|
+
username = `${this._domain}/${this._agent}`
|
|
177
180
|
password = this._token
|
|
181
|
+
} else if (!this._password) {
|
|
182
|
+
username = `${this._domain}/${this._agent}`
|
|
183
|
+
password = this._generateToken()
|
|
178
184
|
}
|
|
179
185
|
this._options = {
|
|
180
186
|
username,
|
|
181
187
|
password,
|
|
182
188
|
keepalive: 30,
|
|
183
189
|
connectTimeout: 10 * 1000,
|
|
184
|
-
clientId:
|
|
190
|
+
clientId: this._mqttClientId,
|
|
185
191
|
rejectUnauthorized: false,
|
|
186
192
|
will: {
|
|
187
193
|
topic: `${this._baseTopic}/__agentInfo__`,
|
|
@@ -194,12 +200,7 @@ class VrpcAgent extends EventEmitter {
|
|
|
194
200
|
this._log.info(`Agent : ${this._agent}`)
|
|
195
201
|
this._log.info(`Broker : ${this._broker}`)
|
|
196
202
|
this._log.info('Connecting to MQTT server...')
|
|
197
|
-
|
|
198
|
-
if (wasEnded) return
|
|
199
|
-
this._client = mqtt.connect(this._broker, {
|
|
200
|
-
...this._options,
|
|
201
|
-
clean: false
|
|
202
|
-
})
|
|
203
|
+
this._client = mqtt.connect(this._broker, this._options)
|
|
203
204
|
this._client.on('connect', this._handleConnect.bind(this))
|
|
204
205
|
this._client.on('reconnect', this._handleReconnect.bind(this))
|
|
205
206
|
this._client.on('error', this._handleError.bind(this))
|
|
@@ -238,16 +239,11 @@ class VrpcAgent extends EventEmitter {
|
|
|
238
239
|
}
|
|
239
240
|
}
|
|
240
241
|
await new Promise(resolve => this._client.end(false, {}, resolve))
|
|
241
|
-
await this._clearPersistedSession()
|
|
242
242
|
} catch (err) {
|
|
243
243
|
this._log.error(err, `Problem during disconnecting agent: ${err.message}`)
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
static _generateUserName () {
|
|
248
|
-
return `${os.userInfo().username}@${os.hostname()}-${os.platform()}-js`
|
|
249
|
-
}
|
|
250
|
-
|
|
251
247
|
static _generateAgentName () {
|
|
252
248
|
const { username } = os.userInfo()
|
|
253
249
|
const pathId = crypto
|
|
@@ -258,6 +254,27 @@ class VrpcAgent extends EventEmitter {
|
|
|
258
254
|
return `${username}-${pathId}@${os.hostname()}-${os.platform()}-js`
|
|
259
255
|
}
|
|
260
256
|
|
|
257
|
+
_generateToken () {
|
|
258
|
+
const uid =
|
|
259
|
+
this._domain +
|
|
260
|
+
this._agent +
|
|
261
|
+
os.userInfo().username +
|
|
262
|
+
path.resolve() +
|
|
263
|
+
os.arch() +
|
|
264
|
+
os.homedir() +
|
|
265
|
+
os.hostname() +
|
|
266
|
+
os.platform() +
|
|
267
|
+
os.release() +
|
|
268
|
+
os.totalmem() +
|
|
269
|
+
os.type() +
|
|
270
|
+
JSON.stringify(os.networkInterfaces()) +
|
|
271
|
+
JSON.stringify(os.cpus().map(({ model }) => model))
|
|
272
|
+
return crypto
|
|
273
|
+
.createHash('md5')
|
|
274
|
+
.update(uid)
|
|
275
|
+
.digest('hex')
|
|
276
|
+
}
|
|
277
|
+
|
|
261
278
|
_validateDomain (domain) {
|
|
262
279
|
if (!domain) throw new Error('The domain must be specified')
|
|
263
280
|
if (domain.match(/[+/#*]/)) {
|
|
@@ -285,27 +302,6 @@ class VrpcAgent extends EventEmitter {
|
|
|
285
302
|
})
|
|
286
303
|
}
|
|
287
304
|
|
|
288
|
-
/**
|
|
289
|
-
* @return {Boolean} true if `agent.end()` was explicitly called
|
|
290
|
-
*/
|
|
291
|
-
async _clearPersistedSession () {
|
|
292
|
-
// Clear potentially existing persisted sessions
|
|
293
|
-
const client = mqtt.connect(this._broker, { ...this._options, clean: true })
|
|
294
|
-
client.on('error', err => this.emit('error', err))
|
|
295
|
-
client.on('offline', () => this.emit('offline'))
|
|
296
|
-
client.on('reconnect', () => this.emit('reconnect'))
|
|
297
|
-
return new Promise(resolve => {
|
|
298
|
-
client.on('connect', () => {
|
|
299
|
-
client.end(false, {}, () => resolve(false))
|
|
300
|
-
})
|
|
301
|
-
// Will be triggered if the user called 'agent.end()'
|
|
302
|
-
this.once('end', () => {
|
|
303
|
-
client.end()
|
|
304
|
-
resolve(true)
|
|
305
|
-
})
|
|
306
|
-
})
|
|
307
|
-
}
|
|
308
|
-
|
|
309
305
|
_mqttPublish (topic, message, options) {
|
|
310
306
|
this._client.publish(
|
|
311
307
|
topic,
|
|
@@ -328,9 +324,38 @@ class VrpcAgent extends EventEmitter {
|
|
|
328
324
|
(err, granted) => {
|
|
329
325
|
if (err) {
|
|
330
326
|
this._log.warn(
|
|
331
|
-
`Could not subscribe to topic '${topic}', because: ${err.message}`
|
|
327
|
+
`Could not subscribe to topic(s) '${topic}', because: ${err.message}`
|
|
332
328
|
)
|
|
333
329
|
} else {
|
|
330
|
+
const topicArray = Array.isArray(topic) ? topic : [topic]
|
|
331
|
+
const erroneousGranted = granted
|
|
332
|
+
.filter(x => x.qos === 128)
|
|
333
|
+
.map(x => x.topic)
|
|
334
|
+
if (erroneousGranted.length > 0) {
|
|
335
|
+
err = new Error(
|
|
336
|
+
`Could not subscribe all ${topicArray.length} topic(s) but got error qos=128 on following ${erroneousGranted.length} topic(s): ${erroneousGranted}`
|
|
337
|
+
)
|
|
338
|
+
err.code = 'SUBSCRIBE_FAILED'
|
|
339
|
+
err.subscribeOptions = options
|
|
340
|
+
this._log.error(err)
|
|
341
|
+
this.emit('error', err)
|
|
342
|
+
}
|
|
343
|
+
const reducedQos = granted.filter(x => x.qos < this._qos)
|
|
344
|
+
if (reducedQos.length > 0) {
|
|
345
|
+
err = new Error(
|
|
346
|
+
`Could not subscribe all ${
|
|
347
|
+
topicArray.length
|
|
348
|
+
} topic(s) at desired qos=${
|
|
349
|
+
this._qos
|
|
350
|
+
} but got reduced qos on following ${
|
|
351
|
+
reducedQos.length
|
|
352
|
+
} topic(s): ${JSON.stringify(reducedQos)}`
|
|
353
|
+
)
|
|
354
|
+
err.code = 'SUBSCRIBE_REDUCED_QOS'
|
|
355
|
+
err.subscribeOptions = options
|
|
356
|
+
this._log.warn(err)
|
|
357
|
+
this.emit('error', err)
|
|
358
|
+
}
|
|
334
359
|
if (granted.length === 0) {
|
|
335
360
|
this._log.debug(`Already subscribed to topic '${topic}'`)
|
|
336
361
|
}
|
|
@@ -375,6 +400,8 @@ class VrpcAgent extends EventEmitter {
|
|
|
375
400
|
resolve()
|
|
376
401
|
} else {
|
|
377
402
|
this._client.once('connect', resolve)
|
|
403
|
+
// Will be triggered if the user called 'agent.end()'
|
|
404
|
+
this.once('end', resolve)
|
|
378
405
|
}
|
|
379
406
|
})
|
|
380
407
|
}
|
|
@@ -413,16 +440,6 @@ class VrpcAgent extends EventEmitter {
|
|
|
413
440
|
|
|
414
441
|
_handleConnect () {
|
|
415
442
|
this._log.info('[OK]')
|
|
416
|
-
if (this._isReconnect) {
|
|
417
|
-
this._publishAgentInfoMessage()
|
|
418
|
-
const classes = this._getClasses()
|
|
419
|
-
classes.forEach(className => {
|
|
420
|
-
this._publishClassInfoMessage(className)
|
|
421
|
-
})
|
|
422
|
-
this.emit('connect')
|
|
423
|
-
this._isReconnect = false
|
|
424
|
-
return
|
|
425
|
-
}
|
|
426
443
|
try {
|
|
427
444
|
const topics = this._generateTopics()
|
|
428
445
|
if (topics.length > 0) this._mqttSubscribe(topics)
|
|
@@ -670,7 +687,6 @@ class VrpcAgent extends EventEmitter {
|
|
|
670
687
|
}
|
|
671
688
|
|
|
672
689
|
_handleReconnect () {
|
|
673
|
-
this._isReconnect = true
|
|
674
690
|
this._log.warn(`Reconnecting to ${this._broker}`)
|
|
675
691
|
this.emit('reconnect')
|
|
676
692
|
}
|