• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# AVSession Development
2
3> **NOTE**
4>
5> All APIs of the **AVSession** module are system APIs and can be called only by system applications.
6
7## Development for the Session Access End
8
9### Basic Concepts
10- **AVMetadata**: media data related attributes, including the IDs of the current media asset, previous media asset, and next media asset, title, author, album, writer, and duration.
11- **AVSessionDescriptor**: descriptor about a media session, including the session ID, session type (audio/video), custom session name (**sessionTag**), and information about the corresponding application (**elementName**).
12- **AVPlaybackState**: information related to the media playback state, including the playback state, position, speed, buffered time, loop mode, and whether the media asset is favorited (**isFavorite**).
13
14### Available APIs
15The table below lists the APIs available for the development of the session access end. The APIs use either a callback or promise to return the result. The APIs listed below use a callback, which provide the same functions as their counterparts that use a promise. For details, see [AVSession Management](../reference/apis/js-apis-avsession.md).
16
17Table 1 Common APIs for session access end development
18
19| API                                                                             | Description         |
20|----------------------------------------------------------------------------------|-------------|
21| createAVSession(context: Context, tag: string, type: AVSessionType, callback: AsyncCallback\<AVSession>): void | Creates a session.|
22| setAVMetadata(data: AVMetadata, callback: AsyncCallback\<void>): void            | Sets session metadata.    |
23| setAVPlaybackState(state: AVPlaybackState, callback: AsyncCallback\<void>): void | Sets the playback state information. |
24| setLaunchAbility(ability: WantAgent, callback: AsyncCallback\<void>): void       | Sets the launcher ability.|
25| getController(callback: AsyncCallback\<AVSessionController>): void                | Obtains the controller of this session.|
26| getOutputDevice(callback: AsyncCallback\<OutputDeviceInfo>): void                 | Obtains the output device information. |
27| activate(callback: AsyncCallback\<void>): void                                    | Activates this session.       |
28| destroy(callback: AsyncCallback\<void>): void                                     | Destroys this session.       |
29
30### How to Develop
311. Import the modules.
32
33   ```js
34   import avSession from '@ohos.multimedia.avsession';
35   import wantAgent from '@ohos.wantAgent';
36   import featureAbility from '@ohos.ability.featureAbility';
37   ```
38
392. Create and activate a session.
40
41   ```js
42   // Define global variables.
43   let mediaFavorite = false;
44   let currentSession = null;
45   let context = featureAbility.getContext();
46
47   // Create an audio session.
48   avSession.createAVSession(context, "AudioAppSample", 'audio').then((session) => {
49      currentSession = session;
50      currentSession.activate(); // Activate the session.
51   }).catch((err) => {
52      console.info(`createAVSession : ERROR : ${err.message}`);
53   });
54   ```
55
563. Set the session information, including:
57
58- Session metadata. In addition to the current media asset ID (mandatory), you can set the title, album, author, duration, and previous/next media asset ID. For details about the session metadata, see **AVMetadata** in the API document.
59- Launcher ability, which is implemented by calling an API of [WantAgent](../reference/apis/js-apis-wantAgent.md). Generally, **WantAgent** is used to encapsulate want information.
60- Playback state information.
61
62  ```js
63  // Set the session metadata.
64  let metadata  = {
65     assetId: "121278",
66     title: "lose yourself",
67     artist: "Eminem",
68     author: "ST",
69     album: "Slim shady",
70     writer: "ST",
71     composer: "ST",
72     duration: 2222,
73     mediaImage: "https://www.example.com/example.jpg",       // Set it based on your project requirements.
74     subtitle: "8 Mile",
75     description: "Rap",
76     lyric: "https://www.example.com/example.lrc",            // Set it based on your project requirements.
77     previousAssetId: "121277",
78     nextAssetId: "121279",
79  };
80  currentSession.setAVMetadata(metadata).then(() => {
81     console.info('setAVMetadata successfully');
82  }).catch((err) => {
83     console.info(`setAVMetadata : ERROR : ${err.message}`);
84  });
85  ```
86
87  ```js
88  // Set the launcher ability.
89  let wantAgentInfo = {
90    wants: [
91      {
92        bundleName: "com.neu.setResultOnAbilityResultTest1",
93        abilityName: "com.example.test.MainAbility",
94      }
95    ],
96    operationType: wantAgent.OperationType.START_ABILITIES,
97    requestCode: 0,
98    wantAgentFlags:[wantAgent.WantAgentFlags.UPDATE_PRESENT_FLAG]
99  }
100
101  wantAgent.getWantAgent(wantAgentInfo).then((agent) => {
102    currentSession.setLaunchAbility(agent).then(() => {
103      console.info('setLaunchAbility successfully');
104    }).catch((err) => {
105      console.info(`setLaunchAbility : ERROR : ${err.message}`);
106    });
107  });
108  ```
109
110  ```js
111  // Set the playback state information.
112  let PlaybackState = {
113    state: avSession.PlaybackState.PLAYBACK_STATE_STOP,
114    speed: 1.0,
115    position:{elapsedTime: 0, updateTime: (new Date()).getTime()},
116    bufferedTime: 1000,
117    loopMode: avSession.LoopMode.LOOP_MODE_SEQUENCE,
118    isFavorite: false,
119  };
120  currentSession.setAVPlaybackState(PlaybackState).then(() => {
121    console.info('setAVPlaybackState successfully');
122  }).catch((err) => {
123    console.info(`setAVPlaybackState : ERROR : ${err.message}`);
124  });
125  ```
126
127  ```js
128  // Obtain the controller of this session.
129  currentSession.getController().then((selfController) => {
130     console.info('getController successfully');
131  }).catch((err) => {
132     console.info(`getController : ERROR : ${err.message}`);
133  });
134  ```
135
136  ```js
137  // Obtain the output device information.
138  currentSession.getOutputDevice().then((outputInfo) => {
139     console.info(`getOutputDevice successfully, deviceName : ${outputInfo.deviceName}`);
140  }).catch((err) => {
141     console.info(`getOutputDevice : ERROR : ${err.message}`);
142  });
143  ```
144
1454. Subscribe to control command events.
146
147   ```js
148   // Subscribe to the 'play' command event.
149   currentSession.on('play', () => {
150      console.log ("Call AudioPlayer.play.");
151      // Set the playback state information.
152      currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PLAY}).then(() => {
153          console.info('setAVPlaybackState successfully');
154      }).catch((err) => {
155          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
156      });
157   });
158
159
160   // Subscribe to the 'pause' command event.
161   currentSession.on('pause', () => {
162      console.log ("Call AudioPlayer.pause.");
163      // Set the playback state information.
164      currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PAUSE}).then(() => {
165          console.info('setAVPlaybackState successfully');
166      }).catch((err) => {
167          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
168      });
169   });
170
171   // Subscribe to the 'stop' command event.
172   currentSession.on('stop', () => {
173      console.log ("Call AudioPlayer.stop.");
174      // Set the playback state information.
175      currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_STOP}).then(() => {
176          console.info('setAVPlaybackState successfully');
177      }).catch((err) => {
178          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
179      });
180   });
181
182   // Subscribe to the 'playNext' command event.
183   currentSession.on('playNext', () => {
184      // When the media file is not ready, download and cache the media file, and set the 'PREPARE' state.
185      currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PREPARE}).then(() => {
186          console.info('setAVPlaybackState successfully');
187      }).catch((err) => {
188          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
189      });
190      // The media file is obtained.
191      currentSession.setAVMetadata({assetId: '58970105', title: 'See you tomorrow'}).then(() => {
192          console.info('setAVMetadata successfully');
193      }).catch((err) => {
194          console.info(`setAVMetadata : ERROR : ${err.message}`);
195      });
196      console.log ("Call AudioPlayer.play.");
197      // Set the playback state information.
198      let time = (new Date()).getTime();
199      currentSession.setAVPlaybackState({state: avSession.PlaybackState.PLAYBACK_STATE_PLAY, position: {elapsedTime: 0, updateTime: time}, bufferedTime:2000}).then(() => {
200          console.info('setAVPlaybackState successfully');
201      }).catch((err) => {
202          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
203      });
204   });
205
206   // Subscribe to the 'fastForward' command event.
207   currentSession.on('fastForward', () => {
208      console.log("Call AudioPlayer for fast forwarding.");
209      // Set the playback state information.
210      currentSession.setAVPlaybackState({speed: 2.0}).then(() => {
211          console.info('setAVPlaybackState successfully');
212      }).catch((err) => {
213          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
214      });
215   });
216
217   // Subscribe to the 'seek' command event.
218   currentSession.on('seek', (time) => {
219      console.log("Call AudioPlayer.seek.");
220      // Set the playback state information.
221      currentSession.setAVPlaybackState({position: {elapsedTime: time, updateTime: (new Data()).getTime()}}).then(() => {
222          console.info('setAVPlaybackState successfully');
223      }).catch((err) => {
224          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
225      });
226   });
227
228   // Subscribe to the 'setSpeed' command event.
229   currentSession.on('setSpeed', (speed) => {
230      console.log(`Call AudioPlayer to set the speed to ${speed}`);
231      // Set the playback state information.
232      currentSession.setAVPlaybackState({speed: speed}).then(() => {
233          console.info('setAVPlaybackState successfully');
234      }).catch((err) => {
235          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
236      });
237   });
238
239   // Subscribe to the 'setLoopMode' command event.
240   currentSession.on('setLoopMode', (mode) => {
241      console.log(`The application switches to the loop mode ${mode}`);
242      // Set the playback state information.
243      currentSession.setAVPlaybackState({loopMode: mode}).then(() => {
244          console.info('setAVPlaybackState successfully');
245      }).catch((err) => {
246          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
247      });
248   });
249
250   // Subscribe to the 'toggleFavorite' command event.
251   currentSession.on('toggleFavorite', (assetId) => {
252      console.log(`The application favorites ${assetId}.`);
253      // Perform the switch based on the last status.
254      let favorite = mediaFavorite == false ? true : false;
255      currentSession.setAVPlaybackState({isFavorite: favorite}).then(() => {
256          console.info('setAVPlaybackState successfully');
257      }).catch((err) => {
258          console.info(`setAVPlaybackState : ERROR : ${err.message}`);
259      });
260      mediaFavorite = favorite;
261   });
262
263   // Subscribe to the key event.
264   currentSession.on('handleKeyEvent', (event) => {
265      console.log(`User presses the key ${event.keyCode}`);
266   });
267
268   // Subscribe to output device changes.
269   currentSession.on('outputDeviceChange', (device) => {
270      console.log(`Output device changed to ${device.deviceName}`);
271   });
272   ```
273
2745. Release resources.
275
276   ```js
277   // Unsubscribe from the events.
278   currentSession.off('play');
279   currentSession.off('pause');
280   currentSession.off('stop');
281   currentSession.off('playNext');
282   currentSession.off('playPrevious');
283   currentSession.off('fastForward');
284   currentSession.off('rewind');
285   currentSession.off('seek');
286   currentSession.off('setSpeed');
287   currentSession.off('setLoopMode');
288   currentSession.off('toggleFavorite');
289   currentSession.off('handleKeyEvent');
290   currentSession.off('outputDeviceChange');
291
292   // Deactivate the session and destroy the object.
293   currentSession.deactivate().then(() => {
294      currentSession.destroy();
295   });
296   ```
297
298### Verification
299Touch the play, pause, or next button on the media application. Check whether the media playback state changes accordingly.
300
301### FAQs
302
3031. Session Service Exception
304- Symptoms
305
306  The session service is abnormal, and the application cannot obtain a response from the session service. For example, the session service is not running or the communication with the session service fails. The error message "Session service exception" is displayed.
307
308- Possible causes
309
310  The session service is killed during session restart.
311
312- Solution
313
314  (1) The system retries the operation automatically. If the error persists for 3 seconds or more, stop the operation on the session or controller.
315
316  (2) Destroy the current session or session controller and re-create it. If the re-creation fails, stop the operation on the session.
317
3182. Session Does Not Exist
319- Symptoms
320
321  Parameters are set for or commands are sent to the session that does not exist. The error message "The session does not exist" is displayed.
322
323- Possible causes
324
325  The session has been destroyed, and no session record exists on the server.
326
327- Solution
328
329  (1) If the error occurs on the application, re-create the session. If the error occurs on Media Controller, stop sending query or control commands to the session.
330
331  (2) If the error occurs on the session service, query the current session record and pass the correct session ID when creating the controller.
332
3333. Session Not Activated
334- Symptoms
335
336  A control command or event is sent to the session when it is not activated. The error message "The session not active" is displayed.
337
338- Possible causes
339
340  The session is in the inactive state.
341
342- Solution
343
344  Stop sending the command or event. Subscribe to the session activation status, and resume the sending when the session is activated.
345
346## Development for the Session Control End (Media Controller)
347
348### Basic Concepts
349- Remote projection: A local media session is projected to a remote device. The local controller sends commands to control media playback on the remote device.
350- Sending key events: The controller controls media playback by sending key events.
351- Sending control commands: The controller controls media playback by sending control commands.
352- Sending system key events: A system application calls APIs to send system key events to control media playback.
353- Sending system control commands: A system application calls APIs to send system control commands to control media playback.
354
355### Available APIs
356
357The table below lists the APIs available for the development of the session control end. The APIs use either a callback or promise to return the result. The APIs listed below use a callback, which provide the same functions as their counterparts that use a promise. For details, see [AVSession Management](../reference/apis/js-apis-avsession.md).
358
359Table 2 Common APIs for session control end development
360
361| API                                                                                           | Description              |
362| ------------------------------------------------------------------------------------------------ | ----------------- |
363| getAllSessionDescriptors(callback: AsyncCallback\<Array\<Readonly\<AVSessionDescriptor>>>): void    | Obtains the descriptors of all sessions. |
364| createController(sessionId: string, callback: AsyncCallback\<AVSessionController>): void          | Creates a controller.         |
365| sendAVKeyEvent(event: KeyEvent, callback: AsyncCallback\<void>): void                            | Sends a key event.       |
366| getLaunchAbility(callback: AsyncCallback\<WantAgent>): void                                      | Obtains the launcher ability.          |
367| sendControlCommand(command: AVControlCommand, callback: AsyncCallback\<void>): void              | Sends a control command.       |
368| sendSystemAVKeyEvent(event: KeyEvent, callback: AsyncCallback\<void>): void                       | Send a system key event.    |
369| sendSystemControlCommand(command: AVControlCommand, callback: AsyncCallback\<void>): void         | Sends a system control command.    |
370| castAudio(session: SessionToken \| 'all', audioDevices: Array\<audio.AudioDeviceDescriptor>, callback: AsyncCallback\<void>): void | Casts the media session to a remote device.|
371
372### How to Develop
3731. Import the modules.
374
375   ```js
376   import avSession from '@ohos.multimedia.avsession';
377   import {Action, KeyEvent} from '@ohos.multimodalInput.KeyEvent';
378   import wantAgent from '@ohos.wantAgent';
379   import audio from '@ohos.multimedia.audio';
380   ```
381
3822. Obtain the session descriptors and create a controller.
383
384   ```js
385   // Define global variables.
386   let g_controller = new Array<avSession.AVSessionController>();
387   let g_centerSupportCmd:Set<avSession.AVControlCommandType> = new Set(['play', 'pause', 'playNext', 'playPrevious', 'fastForward', 'rewind', 'seek','setSpeed', 'setLoopMode', 'toggleFavorite']);
388   let g_validCmd:Set<avSession.AVControlCommandType>;
389
390   // Obtain the session descriptors and create a controller.
391   avSession.getAllSessionDescriptors().then((descriptors) => {
392      descriptors.forEach((descriptor) => {
393          avSession.createController(descriptor.sessionId).then((controller) => {
394              g_controller.push(controller);
395          }).catch((err) => {
396              console.error('createController error');
397          });
398      });
399   }).catch((err) => {
400      console.error('getAllSessionDescriptors error');
401   });
402
403   // Subscribe to the 'sessionCreate' event and create a controller.
404   avSession.on('sessionCreate', (session) => {
405     // After a session is added, you must create a controller.
406     avSession.createController(session.sessionId).then((controller) => {
407       g_controller.push(controller);
408     }).catch((err) => {
409       console.info(`createController : ERROR : ${err.message}`);
410     });
411   });
412   ```
413
4143. Subscribe to the session state and service changes.
415
416   ```js
417   // Subscribe to the 'activeStateChange' event.
418   controller.on('activeStateChange', (isActive) => {
419     if (isActive) {
420       console.log ("The widget corresponding to the controller is highlighted.");
421     } else {
422       console.log("The widget corresponding to the controller is invalid.");
423     }
424   });
425
426   // Subscribe to the 'sessionDestroy' event to enable Media Controller to get notified when the session dies.
427   controller.on('sessionDestroy', () => {
428      console.info('on sessionDestroy : SUCCESS ');
429      controller.destroy().then(() => {
430          console.info('destroy : SUCCESS ');
431      }).catch((err) => {
432          console.info(`destroy : ERROR :${err.message}`);
433      });
434   });
435
436   // Subscribe to the 'sessionDestroy' event to enable the application to get notified when the session dies.
437   avSession.on('sessionDestroy', (session) => {
438      let index = g_controller.findIndex((controller) => {
439          return controller.sessionId == session.sessionId;
440      });
441      if (index != 0) {
442          g_controller[index].destroy();
443          g_controller.splice(index, 1);
444      }
445   });
446
447   // Subscribe to the 'topSessionChange' event.
448   avSession.on('topSessionChange', (session) => {
449      let index = g_controller.findIndex((controller) => {
450          return controller.sessionId == session.sessionId;
451      });
452      // Place the session on the top.
453      if (index != 0) {
454          g_controller.sort((a, b) => {
455              return a.sessionId == session.sessionId ? -1 : 0;
456          });
457      }
458   });
459
460   // Subscribe to the 'sessionServiceDie' event.
461   avSession.on('sessionServiceDie', () => {
462      // The server is abnormal, and the application clears resources.
463      console.log("Server exception");
464   })
465   ```
466
4674. Subscribe to media session information changes.
468
469   ```js
470   // Subscribe to metadata changes.
471   let metaFilter = ['assetId', 'title', 'description'];
472   controller.on('metadataChange', metaFilter, (metadata) => {
473      console.info(`on metadataChange assetId : ${metadata.assetId}`);
474   });
475
476   // Subscribe to playback state changes.
477   let playbackFilter = ['state', 'speed', 'loopMode'];
478   controller.on('playbackStateChange', playbackFilter, (playbackState) => {
479      console.info(`on playbackStateChange state : ${playbackState.state}`);
480   });
481
482   // Subscribe to supported command changes.
483   controller.on('validCommandChange', (cmds) => {
484      console.info(`validCommandChange : SUCCESS : size : ${cmds.size}`);
485      console.info(`validCommandChange : SUCCESS : cmds : ${cmds.values()}`);
486      g_validCmd.clear();
487      for (let c of g_centerSupportCmd) {
488          if (cmds.has(c)) {
489              g_validCmd.add(c);
490          }
491      }
492   });
493
494   // Subscribe to output device changes.
495   controller.on('outputDeviceChange', (device) => {
496      console.info(`on outputDeviceChange device isRemote : ${device.isRemote}`);
497   });
498   ```
499
5005. Control the session behavior.
501
502   ```js
503   // When the user touches the play button, the control command 'play' is sent to the session.
504   if (g_validCmd.has('play')) {
505      controller.sendControlCommand({command:'play'}).then(() => {
506          console.info('sendControlCommand successfully');
507      }).catch((err) => {
508          console.info(`sendControlCommand : ERROR : ${err.message}`);
509      });
510   }
511
512   // When the user selects the single loop mode, the corresponding control command is sent to the session.
513   if (g_validCmd.has('setLoopMode')) {
514      controller.sendControlCommand({command: 'setLoopMode', parameter: avSession.LoopMode.LOOP_MODE_SINGLE}).then(() => {
515          console.info('sendControlCommand successfully');
516      }).catch((err) => {
517          console.info(`sendControlCommand : ERROR : ${err.message}`);
518      });
519   }
520
521   // Send a key event.
522   let keyItem = {code: 0x49, pressedTime: 123456789, deviceId: 0};
523   let event = {action: 2, key: keyItem, keys: [keyItem]};
524   controller.sendAVKeyEvent(event).then(() => {
525      console.info('sendAVKeyEvent Successfully');
526   }).catch((err) => {
527      console.info(`sendAVKeyEvent : ERROR : ${err.message}`);
528   });
529
530   // The user touches the blank area on the widget to start the application.
531   controller.getLaunchAbility().then((want) => {
532      console.log("Starting the application in the foreground");
533   }).catch((err) => {
534      console.info(`getLaunchAbility : ERROR : ${err.message}`);
535   });
536
537   // Send the system key event.
538   let keyItem = {code: 0x49, pressedTime: 123456789, deviceId: 0};
539   let event = {action: 2, key: keyItem, keys: [keyItem]};
540   avSession.sendSystemAVKeyEvent(event).then(() => {
541      console.info('sendSystemAVKeyEvent Successfully');
542   }).catch((err) => {
543      console.info(`sendSystemAVKeyEvent : ERROR : ${err.message}`);
544   });
545
546   // Send a system control command to the top session.
547   let avcommand = {command: 'toggleFavorite', parameter: "false"};
548   avSession.sendSystemControlCommand(avcommand).then(() => {
549      console.info('sendSystemControlCommand successfully');
550   }).catch((err) => {
551      console.info(`sendSystemControlCommand : ERROR : ${err.message}`);
552   });
553
554   // Cast the session to another device.
555   let audioManager = audio.getAudioManager();
556   let audioDevices;
557   await audioManager.getDevices(audio.DeviceFlag.OUTPUT_DEVICES_FLAG).then((data) => {
558      audioDevices = data;
559      console.info('Promise returned to indicate that the device list is obtained.');
560   }).catch((err) => {
561      console.info(`getDevices : ERROR : ${err.message}`);
562   });
563
564   avSession.castAudio('all', audioDevices).then(() => {
565      console.info('createController : SUCCESS');
566   }).catch((err) => {
567      console.info(`createController : ERROR : ${err.message}`);
568   });
569   ```
570
5716. Release resources.
572
573   ```js
574   // Unsubscribe from the events.
575    controller.off('metadataChange');
576    controller.off('playbackStateChange');
577    controller.off('sessionDestroy');
578    controller.off('activeStateChange');
579    controller.off('validCommandChange');
580    controller.off('outputDeviceChange');
581
582    // Destroy the controller.
583    controller.destroy().then(() => {
584        console.info('destroy : SUCCESS ');
585    }).catch((err) => {
586        console.info(`destroy : ERROR : ${err.message}`);
587    });
588   ```
589
590### Verification
591When you touch the play, pause, or next button in Media Controller, the playback state of the application changes accordingly.
592
593### FAQs
5941. Controller Does Not Exist
595- Symptoms
596
597  A control command or an event is sent to the controller that does not exist. The error message "The session controller does not exist" is displayed.
598
599- Possible causes
600
601  The controller has been destroyed.
602
603- Solution
604
605  Query the session record and create the corresponding controller.
606
6072. Remote Session Connection Failure
608- Symptoms
609
610  The communication between the local session and the remote session fails. The error information "The remote session connection failed" is displayed.
611
612- Possible causes
613
614  The communication between devices is interrupted.
615
616- Solution
617
618  Stop sending control commands to the session. Subscribe to output device changes, and resume the sending when the output device is changed.
619
6203. Invalid Session Command
621- Symptoms
622
623  The control command or event sent to the session is not supported. The error message "Invalid session command" is displayed.
624
625- Possible causes
626
627  The session does not support this command.
628
629- Solution
630
631  Stop sending the command or event. Query the commands supported by the session, and send a command supported.
632
6334. Too Many Commands or Events
634- Symptoms
635
636  The session client sends too many messages or commands to the server in a period of time, causing the server to be overloaded. The error message "Command or event overload" is displayed.
637
638- Possible causes
639
640  The server is overloaded with messages or events.
641
642- Solution
643
644  Control the frequency of sending commands or events.
645