import IPostMessage from '../IPostMessage'; import { BroadcastedValueMessage, ClosedMessage, StatusMessage } from './syncMessages'; import { StatusEvent } from './syncEvents'; import ISync from './ISync'; export interface SynchronizerConfig { /** Allow slave devices to broadcast values to all devices in group (default: false) */ allowSlaveBroadcast?: boolean; } /** * The `SyncEngine` enum defines the available synchronization engines that can be used to synchronize devices. * Each engine has its own method of connecting devices and synchronizing data. */ export declare enum SyncEngine { /** Use external sync server. Device will connect to the server via websocket. */ SyncServer = "sync-server", /** Synchronize directly with other devices in the local network via UDP and TCP. */ P2PLocal = "p2p-local", /** * Synchronize directly with other devices in the local network via UDP. * @deprecated use {@link P2PLocal} */ Udp = "udp" } /** * Options for sync-server synchronization. */ export interface ConnectSyncServerOptions { engine?: SyncEngine.SyncServer; /** Address of the sync server engine. If omitted, the default server from device configuration will be used. */ uri?: string; /** Optional configuration for sync server behavior */ config?: SynchronizerConfig; } /** * Options for P2P local synchronization. */ export interface ConnectP2PLocalOptions { engine: SyncEngine.P2PLocal; } /** @deprecated use SyncEngine.P2PLocal and ConnectP2PLocalOptions */ export interface ConnectUdpOptions { engine: SyncEngine.Udp; } /** Options for the `connect()` method based selected synchronization type. */ type SynchronizationEngineOptions = ConnectSyncServerOptions | ConnectP2PLocalOptions | ConnectUdpOptions; /** * The `sos.sync` API groups together methods for synchronization of multiple devices. Devices are synchronized either through an external * server or one of the devices becomes a master device. */ export default class Sync implements ISync { private messagePrefix; private postMessage; static MESSAGE_PREFIX: string; private static DEFAULT_GROUP_NAME; private eventEmitter; /** @internal */ constructor(messagePrefix: string, postMessage: IPostMessage); /** * The `connect()` method initializes the device and connects it to the rest of the devices. This initializes the connection and is * mandatory to call, since synchronization is an optional feature and doesn’t get initialized by default to save resources and bandwidth. * You can optionally specify a custom sync server URI in case you are running the sync server in a custom location. * * :::info * All devices, that should be synchronized together, must select the same engine. Otherwise, they won't be able to communicate with each * other. * ::: * * @param options.engine {SynchronizationEngineOptions} Synchronization engine to use. * @param options.uri Address of the sync server engine. Only relevant for sync-server. If omitted, the default server will be used. * @returns {Promise} A promise that resolves when the connection is established. * @throws Error If unable to connect. * @throws Error If the `uri` is not a valid URL when using the sync-server engine. * @throws Error If the `engine` is not a valid synchronization engine. * @throws Error If any other error occurs during connection. * @since 5.7.0 * * @example // {@link https://github.com/signageos/applet-examples/tree/master/examples/content-js-api/sync-video | How to use synchronizer in applet} * @example // {@link https://github.com/signageos/applet-examples/tree/master/examples/content-js-api/sync-mixed-content | How to synchronize mixed content} * @example * // use default engine * await sos.sync.connect(); * * // use sync-server engine and default server * await sos.sync.connect({ engine: 'sync-server' }); * * // use sync-server engine and custom server * await sos.sync.connect({ engine: 'sync-server', uri: syncServerUri }); * * // use p2p-local engine * await sos.sync.connect({ engine: 'p2p-local' }); */ connect(options?: SynchronizationEngineOptions): Promise; /** * @internal * @deprecated Use `connect({ engine: 'sync-server' })` instead. * * @since 1.0.32 */ connect(options?: string): Promise; /** * The `close()` method disconnects the device from synchronization server and other devices. Recommended to call this method after the * synchronization is not required any longer. * * @returns {Promise} A promise that resolves when the connection is closed. * @throws Error If unable to close the connection. * @since 1.0.32 */ close(): Promise; /** * @deprecated use `sos.sync.joinGroup()` instead. * @since 1.0.32 */ init(groupName?: string, deviceIdentification?: string): Promise; /** * The `joinGroup()` method joins a group of other devices. This method has to be called after `connect()` call. Before any communication * takes place, all participating devices have to be connected and recognize one another. Recommended to call this method early. * * @param options Options for joining a group. * @returns {Promise} A promise that resolves when the device joins the group. * @throws Error If the group name is not a string. * @throws Error If the device identification is not a string. * @throws Error If unable to join the group. * @throws Error If any other error occurs during joining the group. * @since 5.7.0 * * @example // {@link https://github.com/signageos/applet-examples/tree/master/examples/content-js-api/sync-video | How to use synchronizer in applet} * @example * await sos.sync.connect(); * await sos.sync.joinGroup({ groupName: 'my-group', deviceIdentification: 'my-device-id' }); */ joinGroup(options: { groupName?: string; deviceIdentification?: string; }): Promise; /** * The `leaveMethod` method leaves a group of devices. * * @param groupName The name of the group to leave. Defaults to the default group. * @returns {Promise} A promise that resolves when the device leaves the group. * @throws Error If the group name is not a string. * @throws Error If unable to leave the group. * @throws Error If any other error occurs during leaving the group. * @since 5.7.0 * * @example * await sos.sync.leaveGroup('my-group'); */ leaveGroup(groupName?: string): Promise; /** * The `wait()` method synchronizes with other devices by waiting for other devices before proceeding. * * One way to synchronize devices is to make them wait for each other at a certain moment. This would be most commonly used before the * device hits “play” on a video, to make it wait for other devices so they all start playing the video at the same time. * * This method returns a promise that resolves once all the devices meet and are ready to continue together. Any action that results in * visible synchronized behavior should be triggered immediately after and any related background preparations should be called before to * prevent delays. * * Sometimes devices might go out of sync due to unpredictable conditions like loss of internet connection. To ensure re-sync of an out of * sync device, you can pass some data as the first argument. This can be any data that informs the whole group about what content is * about to play next. Once all devices are ready, data from the master device is passed to everyone and the rest of the data is ignored. * Therefore, when implementing your applet you should rely on the result data and not the data that is passed to the wait method as an * argument. * * @param data Optional data to pass to the group. * @param groupName The name of the group to wait for. Defaults to the default group. * @param timeout Timeout in milliseconds. If not specified, the default timeout is 30 seconds. * @returns {Promise} A promise that resolves with the data from the master device when all devices are ready to continue. * @throws Error If the group name is not a string. * @throws Error If the timeout is not a number. * @throws Error If unable to wait for the group. * @throws Error If any other error occurs during waiting for the group. * @since 1.0.32 * * @example * // wait for all devices in the group to be ready * await sos.sync.wait('someData', 'someRandomNameGroup').then((data) => { * // this will be called once all devices are ready * console.log('All devices are ready with data:', data); * }); */ wait(data?: any, groupName?: string, timeout?: number): Promise; /** * The `cancelWait()` method aborts a wait on all devices in a group. Sometimes it's necessary to cancel a pending wait. One such * situation would be when the group has to make a sudden change in content or another behavior but there's a risk that part of the group * already called wait() and is waiting for the rest but the rest will never call it at this point. In order to gracefully clean up any * pending activity, use this method. * * :::warning * Any pending wait will be canceled and the promise will be rejected with an error. * ::: * * @param groupName The name of the group to cancel the wait for. Defaults to the default group. * @returns {Promise} A promise that resolves when the wait is canceled. * @throws Error If the group name is not a string. * @throws Error If unable to cancel the wait. * @throws Error If any other error occurs during canceling the wait. * @since 5.12.0 * * @example * sos.sync.wait('someData', 'someRandomNameGroup').catch((err) => { * // this will happen once cancelWait is called * console.error('wait failed', err); * }); * * // this will cause above wait promise to reject * await sos.sync.cancelWait('someRandomNameGroup'); */ cancelWait(groupName?: string): Promise; /** * @deprecated use `sos.sync.broadcastValue()` instead. * @since 2.0.0 */ setValue(key: string, value: any, groupName?: string): Promise; /** * The `broadcastValue()` method sends a key-value pair to all other devices in a specified group. * * @param groupName {String} The name of the group to broadcast the value to. Defaults to the default group. * @param key {String} The key to broadcast the value under. * @param value {any} The value to broadcast. It can be any valid type * @returns {Promise} A promise that resolves when the value is broadcasted. * @throws Error If the group name is not a string. * @throws Error If the key is not a string. * @throws Error If the value is not a valid type (e.g. object, array, etc.). * @throws Error If unable to broadcast the value. * @throws Error If the value can't be sent * @since 5.7.0 * * @example * // broadcast a value to all devices in the group * await sos.sync.broadcastValue({ * groupName: 'my-group', * key: 'my-key', * value: 'my-value', * }); * * // Received on the other devices: * sos.sync.onValue((key, value, groupName) => { * console.log(`Received value for key ${key} in group ${groupName}:`, value); * }); * */ broadcastValue({ groupName, key, value }: { groupName?: string; key: string; value: any; }): Promise; /** * Returns true if the device is currently the master of the group. * * @param groupName The group name to check for master status. Defaults to the default group. * @return {Promise} A promise that resolves with true if the device is the master, false otherwise. * @since 6.7.0 */ isMaster(groupName?: string): Promise; /** * The `onValue()` method sets up a listener, which is called whenever the device receives a broadcasted message. * * @param listener The listener function to call when a value is broadcasted. * @returns {void} Returns when listener is set up. * @throws Error If the listener is not a function. * @since 2.0.0 */ onValue(listener: (key: string, value: any, groupName?: string) => void): void; /** * The `onStatus()` method sets up a listener, which is called periodically or whenever there is a change (i.e. new device * connects/disconnects to/from the group). * * @param listener The listener function to call when the status changes. * @returns {void} Returns when listener is set up. * @throws Error If the listener is not a function. * @since 2.1.0 */ onStatus(listener: (status: StatusEvent) => void): void; /** * The `onClosed()` method sets up a listener, which is called whenever the device is disconnected from the sync. If it closed because * `close()` was called, it will emit without any arguments. if it closed because of an error, it will emit with an error object as the * first argument. * * @param listener The listener function to call when the sync is closed. * @returns {void} Returns when listener is set up. * @throws Error If the listener is not a function. * @since 5.12.0 */ onClosed(listener: (error?: Error) => void): void; /** * The `removeEventListeners()` method removes all listeners set up on `sos.sync` object. * * @since 2.0.0 */ removeEventListeners(): void; /** @internal */ handleMessageData(data: BroadcastedValueMessage | StatusMessage | ClosedMessage): void; private getMessage; } export {};