senza-sdk 4.3.1-ca3d96f.0 → 4.3.1-e113d43.0

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.
@@ -1,9 +1,7 @@
1
- import { SenzaShakaPlayer as SenzaShakaInterface, shaka } from "../interface/senzaShakaPlayer";
1
+ import { shaka } from "../interface/senzaShakaPlayer";
2
2
 
3
3
  import { remotePlayer, lifecycle, getPlatformInfo } from "./api";
4
4
  import { sdkLogger, iso6393to1 } from "./utils";
5
- import moment from "moment";
6
-
7
5
 
8
6
  // Define custom error category
9
7
  shaka.util.Error.Category.SENZA_PLAYER_ERROR = 50;
@@ -33,7 +31,26 @@ class SenzaError extends shaka.util.Error {
33
31
  }
34
32
 
35
33
 
36
- export class SenzaShakaPlayer extends SenzaShakaInterface {
34
+ /**
35
+ * SenzaShakaPlayer subclass of Shaka that handles both local and remote playback.
36
+ *
37
+ * @class SenzaShakaPlayer
38
+ *
39
+ * @example
40
+ * import { SenzaShakaPlayer } from "./senzaShakaPlayer.js";
41
+ *
42
+ * try {
43
+ * const videoElement = document.getElementById("video");
44
+ * const player = new SenzaShakaPlayer(videoElement);
45
+ * await player.load("http://playable.url/file.mpd");
46
+ * await videoElement.play(); // will start the playback
47
+ *
48
+ * } catch (err) {
49
+ * console.error("SenzaShakaPlayer failed with error", err);
50
+ * }
51
+ */
52
+
53
+ export class SenzaShakaPlayer extends shaka.Player {
37
54
  /** @private {SenzaShakaPlayer|null} Previous instance of the player */
38
55
  static _prevInstance = null;
39
56
 
@@ -55,9 +72,9 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
55
72
  * @private
56
73
  * @type {number}
57
74
  * @description Timeout in milliseconds to wait for playing event
58
- * @default 4000
75
+ * @default 3000
59
76
  */
60
- _playingTimeout = 4000;
77
+ _playingTimeout = 3000;
61
78
 
62
79
  /**
63
80
  * @private
@@ -72,7 +89,7 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
72
89
  * @description Whether to stop remote player on error
73
90
  * @default false
74
91
  */
75
- _shouldStopOnRemotePlayerError = false;
92
+ _shouldStopRemotePlayerOnError = false;
76
93
 
77
94
  /**
78
95
  * @private
@@ -118,7 +135,7 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
118
135
  });
119
136
  }
120
137
  },
121
- "pause": () => {
138
+ "pause" : () => {
122
139
  this._resetPlayPromise();
123
140
  this.remotePlayer.pause()
124
141
  .catch(error => {
@@ -263,15 +280,13 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
263
280
 
264
281
 
265
282
  /**
266
- * Handles errors received by remote player while waiting for the playing event.
267
- * The promise returned to the call for video element play will be rejected.
283
+ * Handles errors for play promises and remote player events.
268
284
  * @private
269
285
  * @param {Error} error - The error object.
270
286
  */
271
287
  _handlePlayPromiseError(error) {
272
288
 
273
289
  sdkLogger.error("Error while waiting for playing event:", error);
274
-
275
290
  if (this._playPromiseReject) {
276
291
  this._playPromiseReject(error);
277
292
  this._playPromiseResolve = null;
@@ -281,48 +296,16 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
281
296
  clearTimeout(this._playTimeoutId);
282
297
  this._playTimeoutId = null;
283
298
  }
284
-
285
299
  }
286
300
 
287
301
  /**
288
- * @private
289
- * @type {number}
290
- * @description Minimum suggested presentation delay in seconds
291
- * @default 15
302
+ * Creates an instance of SenzaShakaPlayer, which is a subclass of shaka.Player.
303
+ *
304
+ * @param {HTMLVideoElement} videoElement - The video element to be used for local playback. This parameter is optional. If not provided, the video element can be attached later using the attach method.
305
+ * @param {HTMLElement=} videoContainer - The videoContainer to construct UITextDisplayer
306
+ * @param {function(shaka.Player)=} dependencyInjector Optional callback
307
+ * which is called to inject mocks into the Player. Used for testing.
292
308
  */
293
- _minSuggestedPresentationDelay = 15;
294
-
295
- /**
296
- * Modifies the suggestedPresentationDelay in the manifest text
297
- * @private
298
- * @param {string} manifestText - The MPD manifest text
299
- * @returns {string} - Modified manifest text , or undefined if no modification was done
300
- */
301
- _updateManifestDelayIfBelowMinimum(manifestText) {
302
- // Look for suggestedPresentationDelay attribute
303
- const match = manifestText.match(/suggestedPresentationDelay="([^"]+)"/);
304
- if (match) {
305
- const durationString = match[1];
306
- const duration = moment.duration(durationString);
307
- const currentDelay = duration.asSeconds();
308
-
309
- sdkLogger.info(`Found suggestedPresentationDelay in manifest: ${currentDelay.toFixed(3)}s`);
310
-
311
- if (currentDelay < this._minSuggestedPresentationDelay) {
312
- // Replace the value in the manifest text with 3 decimal places
313
- manifestText = manifestText.replace(
314
- /suggestedPresentationDelay="[^"]+"/,
315
- `suggestedPresentationDelay="PT${this._minSuggestedPresentationDelay.toFixed(3)}S"`
316
- );
317
- sdkLogger.info(`Updated manifest suggestedPresentationDelay to ${this._minSuggestedPresentationDelay.toFixed(3)}s`);
318
- return manifestText;
319
- }
320
- } else {
321
- sdkLogger.info("suggestedPresentationDelay is not defined at the manifest");
322
- }
323
- return undefined;
324
- }
325
-
326
309
  constructor(videoElement, videoContainer, dependencyInjector) {
327
310
  super(videoElement, videoContainer, dependencyInjector);
328
311
 
@@ -340,14 +323,7 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
340
323
  this._addRemotePlayerEventListeners();
341
324
  SenzaShakaPlayer._prevInstance = this;
342
325
  const playTimeout = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"]?.playingEventTimeout;
343
- this._playingTimeout = (playTimeout >= 0) ? playTimeout * 1000 : this._playingTimeout;
344
-
345
- // Initialize minSuggestedPresentationDelay from UI settings or use default
346
- const uiSettings = getPlatformInfo()?.sessionInfo?.settings?.["ui-streamer"];
347
- if (uiSettings?.minSuggestedPresentationDelay !== undefined) {
348
- this._minSuggestedPresentationDelay = uiSettings.minSuggestedPresentationDelay;
349
- sdkLogger.info(`Using configured minSuggestedPresentationDelay: ${this._minSuggestedPresentationDelay}s`);
350
- }
326
+ this._playingTimeout = (playTimeout >= 0) ? playTimeout*1000 : this._playingTimeout;
351
327
 
352
328
  // if video element is provided, add the listeres here. In this case ,there is no need to call attach.
353
329
  if (videoElement) {
@@ -355,25 +331,8 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
355
331
  sdkLogger.warn("SenzaShakaPlayer constructor Adding videoElement in the constructor is going to be deprecated in the future. Please use attach method instead.");
356
332
  }
357
333
 
358
- this.configure({
359
- manifest: {
360
- defaultPresentationDelay: this._minSuggestedPresentationDelay // in seconds
361
- }
362
- });
363
-
364
- remotePlayer.configure({
365
- minSuggestedPresentationDelay: this._minSuggestedPresentationDelay
366
- });
367
-
368
- this.addEventListener("buffering", () => {
369
- if (this.videoElement) {
370
- sdkLogger.info("Buffering at time:", this.videoElement.currentTime);
371
- }
372
- });
373
-
374
334
  }
375
335
 
376
-
377
336
  _attach(videoElement) {
378
337
  this.videoElement = videoElement;
379
338
 
@@ -420,11 +379,27 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
420
379
  this._attachVideoElementToRemotePlayer();
421
380
  }
422
381
 
382
+ /**
383
+ * Overrides the attach method of shaka.Player to attach the video element.
384
+ *
385
+ * @param {HTMLVideoElement} videoElement - The video element to be used for local playback.
386
+ * @param {boolean} [initializeMediaSource=true] - Whether to initialize the media source.
387
+ */
423
388
  async attach(videoElement, initializeMediaSource = true) {
424
389
  await super.attach(videoElement, initializeMediaSource);
425
390
  this._attach(videoElement);
426
391
  }
427
392
 
393
+ /**
394
+ * Detach the player from the current media element. Leaves the player in a
395
+ * state where it cannot play media, until it has been attached to something
396
+ * else.
397
+ *
398
+ * @param {boolean=} keepAdManager
399
+ *
400
+ * @return {!Promise}
401
+ * @export
402
+ */
428
403
  async detach(keepAdManager = false) {
429
404
  // Clear any pending timeout
430
405
  this._resetPlayPromise();
@@ -455,6 +430,14 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
455
430
  this.videoElement = null;
456
431
  }
457
432
 
433
+ /**
434
+ * Unloads the currently playing stream, if any.
435
+ *
436
+ * @param {boolean=} initializeMediaSource
437
+ * @param {boolean=} keepAdManager
438
+ * @return {!Promise}
439
+ * @export
440
+ */
458
441
  async unload(initializeMediaSource = true, keepAdManager = false) {
459
442
  // Call the remote player's unload method
460
443
  try {
@@ -469,14 +452,27 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
469
452
  await super.unload(initializeMediaSource, keepAdManager);
470
453
  }
471
454
 
455
+ /**
456
+ * Overrides the getTextTracks method to use the remote player's text tracks.
457
+ * @returns {Array} An array of text tracks.
458
+ */
472
459
  getTextLanguages() {
473
460
  return Object.keys(this._textTracksMap);
474
461
  }
475
462
 
463
+ /**
464
+ * Overrides the getAudioTracks method to use the remote player's audio tracks.
465
+ * @returns {Array} An array of audio tracks.
466
+ */
476
467
  getAudioLanguages() {
477
468
  return Object.keys(this._audioTracksMap);
478
469
  }
479
470
 
471
+ /**
472
+ * Overrides the selectAudioLanguage method to use the remote player's audio track selection.
473
+ * @param {string} language - The language to select.
474
+ * @param {string=} role - The role of the track to select. (e.g. 'main', 'caption', or 'commentary')
475
+ */
480
476
  selectAudioLanguage(language, role) {
481
477
  sdkLogger.log("Selecting audio language:", language, "with role: ", role);
482
478
  if (this._audioTracksMap[language]) {
@@ -487,6 +483,11 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
487
483
  super.selectAudioLanguage(language, role);
488
484
  }
489
485
 
486
+ /**
487
+ * Overrides the selectTextLanguage method to use the remote player's text track selection.
488
+ * @param {string} language - The language to select.
489
+ * @param {string=} role - The role of the track to select.
490
+ */
490
491
  selectTextLanguage(language, role) {
491
492
  sdkLogger.log("Selecting text language:", language, "with role:", role);
492
493
  if (this._textTracksMap[language]) {
@@ -497,12 +498,20 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
497
498
  super.selectTextLanguage(language, role);
498
499
  }
499
500
 
501
+ /**
502
+ * Overrides the setTextTrackVisibility method to use the remote player's text track visibility settings.
503
+ * @param {boolean} visible - Whether the text tracks should be visible.
504
+ */
500
505
  setTextTrackVisibility(visible) {
501
506
  sdkLogger.log("Setting text track visibility to:", visible);
502
507
  remotePlayer.setTextTrackVisibility(visible);
503
508
  super.setTextTrackVisibility(visible);
504
509
  }
505
510
 
511
+ /**
512
+ * Helper function that makes it easier to check if lifecycle.state is
513
+ * either background or inTransitionToBackground.
514
+ */
506
515
  get isInRemotePlayback() {
507
516
  return lifecycle.state === lifecycle.UiState.BACKGROUND || lifecycle.state === lifecycle.UiState.IN_TRANSITION_TO_BACKGROUND;
508
517
  }
@@ -547,12 +556,11 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
547
556
  const isCritical = this._isErrorCritical(remotePlayerErrorCode);
548
557
  const error = this._createSenzaError(remotePlayerErrorCode, message, isCritical);
549
558
  const errorMap = new Map();
550
- const shouldStopPlayback = this._shouldStopOnRemotePlayerError && this.videoElement && isCritical;
551
559
  errorMap.set("detail", error);
552
560
 
553
561
  // Check if we should stop playback - only for critical errors when configured
554
-
555
- if (shouldStopPlayback) {
562
+ if (this._shouldStopRemotePlayerOnError &&
563
+ this.videoElement && isCritical) {
556
564
  try {
557
565
  sdkLogger.warn("Stopping local player playback due to critical error");
558
566
  // Stop only local playback
@@ -560,14 +568,18 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
560
568
  } catch (stopError) {
561
569
  sdkLogger.error("Error while trying to stop video element playback:", stopError);
562
570
  }
563
- // Handle error while waiting for play event. If the error is not critical or the system is configured not to stop remote player on error,
564
- // the playback timeout will start the local playback
565
- this._handlePlayPromiseError(error);
566
571
  }
567
-
572
+ // Handle error while waiting for play event
573
+ this._handlePlayPromiseError(error);
568
574
  this.dispatchEvent(new shaka.util.FakeEvent("error", errorMap));
569
575
  }
570
576
 
577
+ /**
578
+ * Loads a media URL into both local and remote players.
579
+ *
580
+ * @param {string} url - The URL of the media to load.
581
+ * @returns {Promise<void>}
582
+ */
571
583
  async load(url, startTime, mimeType) {
572
584
 
573
585
  // Create a promise that will resolve when _remotePlayerLoad is called
@@ -596,30 +608,16 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
596
608
 
597
609
  // This callbakc will be activated when the manifest is loaded. It will trigger load of the remote player.
598
610
  // This will ensure that the remote player is loaded only after the manifest is loaded by local player.
599
- const responseFilterCallback = async (type, response) => {
600
- if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST) {
611
+ const responseFilterCallback = async (type) => {
612
+ if (type === shaka.net.NetworkingEngine.RequestType.MANIFEST && !manifestLoadHandled) {
613
+ manifestLoadHandled = true;
601
614
  try {
602
- if (response.data && this._minSuggestedPresentationDelay > 0) {
603
- const manifestText = new TextDecoder().decode(response.data);
604
- const modifiedText = this._updateManifestDelayIfBelowMinimum(manifestText);
605
- if (modifiedText) {
606
- const responseData = new TextEncoder().encode(modifiedText).buffer;
607
- response.data = responseData;
608
- }
609
- }
615
+ await this._remotePlayerLoad(url, startTime);
616
+ remoteLoadResolver();
610
617
  } catch (error) {
611
- sdkLogger.error("Error processing manifest:", error);
618
+ remoteLoadRejecter(error);
612
619
  }
613
620
 
614
- if (!manifestLoadHandled) {
615
- manifestLoadHandled = true;
616
- try {
617
- await this._remotePlayerLoad(url, startTime);
618
- remoteLoadResolver();
619
- } catch (error) {
620
- remoteLoadRejecter(error);
621
- }
622
- }
623
621
  }
624
622
  };
625
623
 
@@ -654,6 +652,13 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
654
652
 
655
653
  }
656
654
 
655
+ /***
656
+ *
657
+ * Configure the Player instance.
658
+ * @param {Object} config the configuration object
659
+ * @returns {Boolean}
660
+ */
661
+
657
662
  async destroy() {
658
663
  await lifecycle.moveToForeground();
659
664
  SenzaShakaPlayer._prevInstance = null;
@@ -661,6 +666,10 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
661
666
  return super.destroy();
662
667
  }
663
668
 
669
+ /**
670
+ * A temporary override for older versions of Shaka.
671
+ * Senza doesn't support out-of-band subtitles
672
+ */
664
673
  addTextTrack(uri, language, kind, mimeType, codec, label, forced = false) {
665
674
  sdkLogger.warn("addTextTrack is deprecated, please use addTextTrackAsync");
666
675
  super.addTextTrackAsync(uri, language, kind, mimeType, codec, label, forced).then(subs => {
@@ -668,16 +677,30 @@ export class SenzaShakaPlayer extends SenzaShakaInterface {
668
677
  });
669
678
  }
670
679
 
680
+ /**
681
+ * Override the configure method to add custom configuration handling
682
+ * Supports the following additional configuration options:
683
+ * - shouldStopRemotePlayerOnError: boolean - If true, remote player will be stopped on error
684
+ *
685
+ * @override
686
+ * @param {Object} config - Configuration object to be merged with existing config
687
+ * @param {boolean} [config.shouldStopRemotePlayerOnError=true] - Whether to stop remote player on error
688
+ * @example
689
+ * player.configure({
690
+ * shouldStopRemotePlayerOnError: false, // Don't stop remote player on error
691
+ * // ... other shaka configurations
692
+ * });
693
+ */
671
694
  configure(config) {
672
695
  sdkLogger.log("configure player with: ", JSON.stringify(config));
673
696
 
674
697
  // Handle custom configuration
675
- if (config.shouldStopOnRemotePlayerError !== undefined) {
676
- this._shouldStopOnRemotePlayerError = !!config.shouldStopOnRemotePlayerError;
698
+ if (config.shouldStopRemotePlayerOnError !== undefined) {
699
+ this._shouldStopRemotePlayerOnError = !!config.shouldStopRemotePlayerOnError;
677
700
  // Remove our custom config so it doesn't get passed to parent
678
701
  // Use rest operator without creating a named variable for the removed property
679
702
  // eslint-disable-next-line no-unused-vars
680
- const { shouldStopOnRemotePlayerError, ...shakaConfig } = config;
703
+ const { shouldStopRemotePlayerOnError, ...shakaConfig } = config;
681
704
  config = shakaConfig;
682
705
  }
683
706
 
@@ -1,28 +1,31 @@
1
1
  import { noop } from "./utils";
2
-
3
- /**
4
- * alarm event
5
- *
6
- * @event AlarmManager#MyAlarm
7
- * @description Fired when time of 'MyAlarm' arrives. If this alarm triggers the application load and the application doesn't call
8
- * lifecycle.moveToForeground() in the alarm callback (i.e. the application remains in the background after the callback is completed),
9
- * the application will be unloaded.
10
- * NOTE: If you perform async operations in the callback (without moving to foreground), you must wait for the async
11
- * operation to finish before returning from the callback, otherwise the application will be unloaded before the async operation is finished.<br>
12
- * @example
13
- * alarmManager.addEventListener("MyAlarm", async (e) => {
14
- * console.log("alarm MyAlarm arrived with data", e.detail);
15
- * await fetch("http://www.example.com");
16
- * });
17
- * alarmManager.addAlarm("MyAlarm", Date.now() + 60*60*1000, "MyData");
18
- */
19
-
20
2
  /**
3
+ * @class AlarmManager
21
4
  * AlarmManager is a singleton class that manages the alarms in the application. It fires events whose types are the names of the alarms.
22
5
  * @fires MyAlarm
23
6
  */
24
7
  export class AlarmManager extends EventTarget {
25
8
 
9
+ /**
10
+ * alarm event
11
+ *
12
+ * @event AlarmManager#MyAlarm
13
+ * @description Fired when time of 'MyAlarm' arrives. If this alarm triggers the application load and the application doesn't call
14
+ * lifecycle.moveToForeground() in the alarm callback (i.e. the application remains in the background after the callback is completed),
15
+ * the application will be unloaded.
16
+ * NOTE: If you perform async operations in the callback (without moving to foreground), you must wait for the async
17
+ * operation to finish before returning from the callback, otherwise the application will be unloaded before the async operation is finished.<br>
18
+ * @example
19
+ * alarmManager.addEventListener("MyAlarm", async (e) => {
20
+ * console.log("alarm MyAlarm arrived with data", e.detail);
21
+ * await fetch("http://www.example.com");
22
+ * });
23
+ * alarmManager.addAlarm("MyAlarm", Date.now() + 60*60*1000, "MyData");
24
+ */
25
+ constructor() {
26
+ super();
27
+ }
28
+
26
29
  addEventListener(type, callback) {
27
30
  noop("AlarmManager.addEventListener", type, callback);
28
31
  }
@@ -64,13 +67,3 @@ export class AlarmManager extends EventTarget {
64
67
  return noop("AlarmManager.getActiveAlarms");
65
68
  }
66
69
  }
67
-
68
- /**
69
- * @module
70
- * @type {AlarmManager}
71
- * @example
72
- * import { alarmManager } from "senza-sdk";
73
- *
74
- * @return {AlarmManager} pointer to the AlarmManager singleton
75
- */
76
- "needed for the module doc comment to be recognized";
@@ -204,7 +204,6 @@ const setupSequence = (components, items) => {
204
204
  };
205
205
  methodInject(components, inject, (name) => name.startsWith("_") || name.startsWith("get"));
206
206
  handleKeys(items);
207
- playersEvents(components, items);
208
207
  sdkLogger.log("Sequence initialized.");
209
208
  };
210
209
 
@@ -258,37 +257,3 @@ export const showSequence = (visible = true) => {
258
257
  }
259
258
  container.style.visibility = visible ? "visible" : "hidden";
260
259
  };
261
- function playersEvents(components, items) {
262
- components.remotePlayer.addEventListener("videoelementattached", () => {
263
- const video = components.remotePlayer._videoElement;
264
- if (video && !video._devSequenceRateChangeHandler) {
265
- video._devSequenceRateChangeHandler = () => {
266
- items.push({
267
- component: "localPlayer",
268
- id: "ratechange=" + video.playbackRate,
269
- time: performance.now() - currentTime
270
- });
271
- };
272
- video.addEventListener("ratechange", video._devSequenceRateChangeHandler);
273
- }
274
-
275
- if (video && !video._devSequencePlayingHandler) {
276
- video._devSequencePlayingHandler = () => {
277
- items.push({
278
- component: "localPlayer",
279
- id: "playing event",
280
- time: performance.now() - currentTime
281
- });
282
- };
283
- video.addEventListener("playing", video._devSequencePlayingHandler);
284
- }
285
- });
286
- components.remotePlayer.addEventListener("playing", () => {
287
- items.push({
288
- component: "remotePlayer",
289
- id: "playing event",
290
- time: performance.now() - currentTime
291
- });
292
- });
293
- }
294
-
@@ -1,24 +1,30 @@
1
1
  import { sdkLogger, noop } from "./utils.js";
2
2
 
3
- const wifiInfo = {
4
- level: 0,
5
- quality: 0,
6
- ssid: "unknown",
7
- bssid: "unknown"
8
- };
9
- /**
10
- * @deprecated Instead, call deviceManager.getWifiInfo() periodically
11
- * @event DeviceManager#wifiInfoUpdated
12
- * @example
13
- * deviceManager.addEventListener("wifiInfoUpdated", () => {
14
- * console.info("Wifi info has been updated to", deviceManager.wifiInfo);
15
- * });
16
- *
17
- */
3
+ const wifiInfo = {};
4
+
18
5
  /**
6
+ * @class DeviceManager
19
7
  * DeviceManager is a singleton class that manages the device
20
8
  */
21
9
  export class DeviceManager extends EventTarget {
10
+
11
+ constructor() {
12
+ super();
13
+ wifiInfo.level = 0;
14
+ wifiInfo.quality = 0;
15
+ wifiInfo.ssid = "unknown";
16
+ wifiInfo.bssid = "unknown";
17
+ /**
18
+ * @deprecated Instead, call deviceManager.getWifiInfo() periodically
19
+ * @event DeviceManager#wifiInfoUpdated
20
+ * @example
21
+ * deviceManager.addEventListener("wifiInfoUpdated", () => {
22
+ * console.info("Wifi info has been updated to", deviceManager.wifiInfo);
23
+ * });
24
+ *
25
+ */
26
+ }
27
+
22
28
  /**
23
29
  * @property {object} DeviceInfo
24
30
  * @property {string} DeviceInfo.deviceId
@@ -125,18 +131,3 @@ export class DeviceManager extends EventTarget {
125
131
  return Promise.resolve({});
126
132
  }
127
133
  }
128
-
129
-
130
- /**
131
- * @module
132
- * @type {DeviceManager}
133
- * @example
134
- * import { deviceManager } from "senza-sdk";
135
- * const wifiInfo = await deviceManager.getWifiInfo();
136
- * console.info(wifiInfo.ssid);
137
- * await deviceManager.clearWifi();
138
- * deviceManager.reboot();
139
- *
140
- * @return {DeviceManager} pointer to the DeviceManager singleton
141
- */
142
- "needed for the module doc comment to be recognized";