pxt-common-packages 9.3.5 → 9.3.9

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/libs/mqtt/mqtt.ts CHANGED
@@ -155,13 +155,20 @@ namespace mqtt {
155
155
  * Structure of an MQTT Control Packet
156
156
  * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800392
157
157
  */
158
- function createPacket(byte1: number, variable: Buffer, payload?: Buffer): Buffer {
159
- if (payload == null) payload = control.createBuffer(0);
160
- const byte2: number[] = encodeRemainingLength(variable.length + payload.length);
158
+ function createPacketHeader(byte1: number, variable: Buffer, payloadSize: number): Buffer {
159
+ const byte2: number[] = encodeRemainingLength(variable.length + payloadSize);
161
160
  return strChr([byte1])
162
161
  .concat(strChr(byte2))
163
162
  .concat(variable)
164
- .concat(payload)
163
+ }
164
+
165
+ /**
166
+ * Structure of an MQTT Control Packet
167
+ * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800392
168
+ */
169
+ function createPacket(byte1: number, variable: Buffer, payload?: Buffer): Buffer {
170
+ if (payload == null) payload = control.createBuffer(0);
171
+ return createPacketHeader(byte1, variable, payload.length).concat(payload)
165
172
  }
166
173
 
167
174
  /**
@@ -208,17 +215,17 @@ namespace mqtt {
208
215
  }
209
216
 
210
217
  /**
211
- * PUBLISH - Publish message
218
+ * PUBLISH - Publish message header - doesn't include "payload"
212
219
  * http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/os/mqtt-v3.1.1-os.html#_Toc384800410
213
220
  */
214
- export function createPublish(topic: string, message: Buffer, qos: number, retained: boolean) {
221
+ export function createPublishHeader(topic: string, payloadSize: number, qos: number, retained: boolean) {
215
222
  let byte1: number = ControlPacketType.Publish << 4 | (qos << 1);
216
223
  byte1 |= (retained) ? 1 : 0;
217
224
 
218
225
  const pid = strChr(getBytes(Constants.FixedPackedId));
219
226
  const variable = (qos === 0) ? pack(topic) : pack(topic).concat(pid);
220
227
 
221
- return createPacket(byte1, variable, message);
228
+ return createPacketHeader(byte1, variable, payloadSize);
222
229
  }
223
230
 
224
231
  export function parsePublish(cmd: number, payload: Buffer): IMessage {
@@ -309,12 +316,25 @@ namespace mqtt {
309
316
  }
310
317
  }
311
318
 
319
+ export enum Status {
320
+ Disconnected = 0,
321
+ Connecting = 1,
322
+ Connected = 2,
323
+ Sending = 3,
324
+ }
325
+
312
326
  export class Client extends EventEmitter {
313
- public logPriority: ConsolePriority;
327
+ public logPriority = ConsolePriority.Debug
328
+ public tracePriority = -1 as ConsolePriority;
329
+
314
330
  private log(msg: string) {
315
331
  console.add(this.logPriority, `mqtt: ${msg}`);
316
332
  }
317
333
 
334
+ private trace(msg: string) {
335
+ console.add(this.tracePriority, `mqtt: ${msg}`);
336
+ }
337
+
318
338
  public opt: IConnectionOptions;
319
339
 
320
340
  private net: net.Net;
@@ -325,7 +345,11 @@ namespace mqtt {
325
345
 
326
346
  private buf: Buffer;
327
347
 
328
- public connected: boolean;
348
+ public status = Status.Disconnected
349
+
350
+ get connected() {
351
+ return this.status >= Status.Connected
352
+ }
329
353
 
330
354
  private mqttHandlers: MQTTHandler[];
331
355
 
@@ -334,8 +358,6 @@ namespace mqtt {
334
358
 
335
359
  this.wdId = Constants.Uninitialized;
336
360
  this.piId = Constants.Uninitialized;
337
- this.logPriority = ConsolePriority.Debug;
338
- this.connected = false;
339
361
  opt.port = opt.port || 8883;
340
362
  opt.clientId = opt.clientId;
341
363
 
@@ -385,15 +407,19 @@ namespace mqtt {
385
407
  this.piId = Constants.Uninitialized;
386
408
  }
387
409
 
388
- if (this.sct) {
389
- //this.sct.removeAllListeners('connect');
390
- //this.sct.removeAllListeners('data');
391
- //this.sct.removeAllListeners('close');
392
- this.sct.close();
410
+ const s = this.sct
411
+ if (s) {
412
+ this.sct = null
413
+ s.close()
393
414
  }
415
+
416
+ this.status = Status.Disconnected
394
417
  }
395
418
 
396
419
  public connect(): void {
420
+ if (this.status != Status.Disconnected)
421
+ return
422
+ this.status = Status.Connecting
397
423
  this.log(`Connecting to ${this.opt.host}:${this.opt.port}`);
398
424
  if (this.wdId === Constants.Uninitialized) {
399
425
  this.wdId = setInterval(() => {
@@ -413,7 +439,7 @@ namespace mqtt {
413
439
  this.send(Protocol.createConnect(this.opt));
414
440
  });
415
441
  this.sct.onMessage((msg: Buffer) => {
416
- this.log("incoming " + msg.length + " bytes")
442
+ this.trace("incoming " + msg.length + " bytes")
417
443
  this.handleMessage(msg);
418
444
  });
419
445
  this.sct.onError(() => {
@@ -423,21 +449,63 @@ namespace mqtt {
423
449
  this.sct.onClose(() => {
424
450
  this.log('Close.');
425
451
  this.emit('disconnected');
426
- this.connected = false;
452
+ this.status = Status.Disconnected
453
+ this.sct = null;
427
454
  });
428
455
  this.sct.connect();
429
456
  }
430
457
 
458
+ private canSend() {
459
+ let cnt = 0
460
+ while (true) {
461
+ if (this.status == Status.Connected) {
462
+ this.status = Status.Sending
463
+ return true
464
+ }
465
+ if (cnt++ < 100 && this.status == Status.Sending)
466
+ pause(20)
467
+ else {
468
+ this.log("drop pkt")
469
+ return false
470
+ }
471
+ }
472
+ }
473
+
474
+ private doneSending() {
475
+ this.trace("done send")
476
+ if (this.status == Status.Sending)
477
+ this.status = Status.Connected
478
+ }
479
+
431
480
  // Publish a message
432
481
  public publish(topic: string, message?: string | Buffer, qos: number = Constants.DefaultQos, retained: boolean = false): void {
433
482
  const buf = typeof message == "string" ? control.createBufferFromUTF8(message) : message
434
- this.log(`publish: ${topic}`)
435
- this.send(Protocol.createPublish(topic, buf, qos, retained));
483
+ message = null
484
+ if (this.startPublish(topic, buf ? buf.length : 0, qos, retained)) {
485
+ if (buf)
486
+ this.send(buf);
487
+ this.doneSending()
488
+ }
489
+ }
490
+
491
+ public startPublish(topic: string, messageLen: number, qos: number = Constants.DefaultQos, retained: boolean = false) {
492
+ if (!this.canSend()) return false
493
+ this.trace(`publish: ${topic} ${messageLen}b`)
494
+ this.send(Protocol.createPublishHeader(topic, messageLen, qos, retained));
495
+ return true
496
+ }
497
+
498
+ public continuePublish(data: Buffer) {
499
+ this.send(data)
500
+ }
501
+
502
+ public finishPublish() {
503
+ this.doneSending()
436
504
  }
437
505
 
438
506
  private subscribeCore(topic: string, handler: (msg: IMessage) => void, qos: number = Constants.DefaultQos): MQTTHandler {
439
507
  this.log(`subscribe: ${topic}`)
440
- this.send(Protocol.createSubscribe(topic, qos));
508
+ this.send1(Protocol.createSubscribe(topic, qos));
441
509
  if (handler) {
442
510
  if (topic[topic.length - 1] == "#")
443
511
  topic = topic.slice(0, topic.length - 1)
@@ -474,8 +542,8 @@ namespace mqtt {
474
542
 
475
543
  private send(data: Buffer): void {
476
544
  if (this.sct) {
477
- //this.log("send: " + data[0] + " / " + data.length + " bytes")
478
- this.log("send: " + data[0] + " / " + data.length + " bytes: " + data.toHex())
545
+ this.trace("send: " + data[0] + " / " + data.length + " bytes")
546
+ // this.log("send: " + data[0] + " / " + data.length + " bytes: " + data.toHex())
479
547
  this.sct.send(data);
480
548
  }
481
549
  }
@@ -518,17 +586,18 @@ namespace mqtt {
518
586
  if (returnCode === ConnectReturnCode.Accepted) {
519
587
  this.log('MQTT connection accepted.');
520
588
  this.emit('connected');
521
- this.connected = true;
589
+ this.status = Status.Connected;
522
590
  this.piId = setInterval(() => this.ping(), Constants.PingInterval * 1000);
523
591
  } else {
524
592
  const connectionError: string = Client.describe(returnCode);
525
593
  this.log('MQTT connection error: ' + connectionError);
526
594
  this.emit('error', connectionError);
595
+ this.disconnect()
527
596
  }
528
597
  break;
529
598
  case ControlPacketType.Publish:
530
599
  const message: IMessage = Protocol.parsePublish(cmd, payload);
531
- this.log(`incoming: ${message.topic}`)
600
+ this.trace(`incoming: ${message.topic}`)
532
601
  let handled = false
533
602
  let cleanup = false
534
603
  if (this.mqttHandlers) {
@@ -548,7 +617,7 @@ namespace mqtt {
548
617
  this.emit('receive', message);
549
618
  if (message.qos > 0) {
550
619
  setTimeout(() => {
551
- this.send(Protocol.createPubAck(message.pid || 0));
620
+ this.send1(Protocol.createPubAck(message.pid || 0));
552
621
  }, 0);
553
622
  }
554
623
  break;
@@ -564,8 +633,15 @@ namespace mqtt {
564
633
  this.handleMessage(data.slice(payloadEnd))
565
634
  }
566
635
 
636
+ private send1(msg: Buffer) {
637
+ if (this.canSend()) {
638
+ this.send(msg)
639
+ this.doneSending()
640
+ }
641
+ }
642
+
567
643
  private ping() {
568
- this.send(Protocol.createPingReq());
644
+ this.send1(Protocol.createPingReq());
569
645
  this.emit('debug', 'Sent: Ping request.');
570
646
  }
571
647
  }