import { IConnection } from "./connection" ; import { GatewayCommand , IGW_FRAME_RCV , GW_COMMON_STATUS } from "./KLF200-API/common" ; import { GW_GET_SCENE_LIST_NTF } from "./KLF200-API/GW_GET_SCENE_LIST_NTF" ; import { GW_GET_SCENE_LIST_REQ } from "./KLF200-API/GW_GET_SCENE_LIST_REQ" ; import { TypedEvent , Listener , Disposable } from "./utils/TypedEvent" ; import { GW_SCENE_INFORMATION_CHANGED_NTF , SceneChangeType } from "./KLF200-API/GW_SCENE_INFORMATION_CHANGED_NTF" ; import { GW_SESSION_FINISHED_NTF } from "./KLF200-API/GW_SESSION_FINISHED_NTF" ; import { GW_ACTIVATE_SCENE_CFM } from "./KLF200-API/GW_ACTIVATE_SCENE_CFM" ; import { GW_ACTIVATE_SCENE_REQ } from "./KLF200-API/GW_ACTIVATE_SCENE_REQ" ; import { ActivateSceneStatus } from "./KLF200-API/GW_SCENES" ; import { GW_GET_SCENE_INFORMATION_NTF , SceneInformationEntry } from "./KLF200-API/GW_GET_SCENE_INFORMATION_NTF" ; import { GW_GET_SCENE_INFORMATION_CFM } from "./KLF200-API/GW_GET_SCENE_INFORMATION_CFM" ; import { GW_GET_SCENE_INFORMATION_REQ } from "./KLF200-API/GW_GET_SCENE_INFORMATION_REQ" ; import { Component } from "./utils/PropertyChangedEvent" ; import { GW_STOP_SCENE_CFM } from "./KLF200-API/GW_STOP_SCENE_CFM" ; import { GW_STOP_SCENE_REQ } from "./KLF200-API/GW_STOP_SCENE_REQ" ; import { GW_GET_SCENE_LIST_CFM } from "./KLF200-API/GW_GET_SCENE_LIST_CFM" ; import { CommandOriginator , PriorityLevel } from "./KLF200-API/GW_COMMAND" ; import { Velocity } from "./KLF200-API/GW_SYSTEMTABLE_DATA" ; "use strict" ; export class extends Component export class Scene extends Component { private _isRunning : boolean = false ; private _runningSession : number = - 1 ; private _sceneName : string ; type { SceneInformationEntry [ ] } memberof public readonly Products : SceneInformationEntry [ ] = [ ] ; param { IConnection } Connection param { number } SceneID param { string } SceneName memberof constructor ( readonly Connection , readonly SceneID , SceneName ) { super ( ) ; this . _sceneName = SceneName ; this . Connection . on ( frame => this . onNotificationHandler ( frame ) , [ GatewayCommand . GW_SESSION_FINISHED_NTF ] ) ; } readonly type { string } memberof public get SceneName ( ) : string { return this . _sceneName ; } readonly type { boolean } memberof public get IsRunning ( ) : boolean { return this . _isRunning ; } param Velocity param PriorityLevel param CommandOriginator returns { Promise < number > } memberof public async runAsync ( Velocity = 0 , PriorityLevel = 3 , CommandOriginator = 1 ) { try { const confirmationFrame = < GW_ACTIVATE_SCENE_CFM > await this . Connection . sendFrameAsync ( new GW_ACTIVATE_SCENE_REQ ( this . SceneID , PriorityLevel , CommandOriginator , Velocity ) ) ; if ( confirmationFrame . Status === ActivateSceneStatus . OK ) { this . _isRunning = true ; this . _runningSession = confirmationFrame . SessionID ; this . propertyChanged ( "IsRunning" ) ; return confirmationFrame . SessionID ; } else { return Promise . reject ( new Error ( confirmationFrame . getError ( ) ) ) ; } } catch ( error ) { return Promise . reject ( error ) ; } } param PriorityLevel param CommandOriginator returns { Promise < number > } memberof public async stopAsync ( PriorityLevel = 3 , CommandOriginator = 1 ) { try { const confirmationFrame = < GW_STOP_SCENE_CFM > await this . Connection . sendFrameAsync ( new GW_STOP_SCENE_REQ ( this . SceneID , PriorityLevel , CommandOriginator ) ) ; if ( confirmationFrame . Status === ActivateSceneStatus . OK ) { this . _isRunning = false ; this . _runningSession = confirmationFrame . SessionID ; this . propertyChanged ( "IsRunning" ) ; return confirmationFrame . SessionID ; } else { return Promise . reject ( new Error ( confirmationFrame . getError ( ) ) ) ; } } catch ( error ) { return Promise . reject ( error ) ; } } returns { Promise < void > } memberof public async refreshAsync ( ) { let dispose ; try { const tempResult = [ ] ; const notificationHandler = new Promise < void > ( ( resolve , reject ) => { try { dispose = this . Connection . on ( frame => { if ( frame instanceof GW_GET_SCENE_INFORMATION_NTF && frame . SceneID === this . SceneID ) { tempResult . push ( ... frame . Nodes ) ; if ( frame . NumberOfRemainingNodes === 0 ) { if ( dispose ) { dispose . dispose ( ) ; } this . Products . length = 0 ; this . Products . push ( ... tempResult ) ; this . propertyChanged ( "Products" ) ; if ( frame . Name !== this . _sceneName ) { this . _sceneName = frame . Name ; this . propertyChanged ( "SceneName" ) ; } resolve ( ) ; } } } , [ GatewayCommand . GW_GET_SCENE_INFORMATION_NTF ] ) ; } catch ( error ) { if ( dispose ) { dispose . dispose ( ) ; } reject ( error ) ; } } ) ; const confirmationFrame = < GW_GET_SCENE_INFORMATION_CFM > await this . Connection . sendFrameAsync ( new GW_GET_SCENE_INFORMATION_REQ ( this . SceneID ) ) ; if ( confirmationFrame . SceneID === this . SceneID ) { if ( confirmationFrame . Status !== GW_COMMON_STATUS . SUCCESS ) { if ( dispose ) { dispose . dispose ( ) ; } return Promise . reject ( new Error ( confirmationFrame . getError ( ) ) ) ; } } return notificationHandler ; } catch ( error ) { if ( dispose ) { dispose . dispose ( ) ; } return Promise . reject ( error ) ; } } private onNotificationHandler ( frame ) { if ( frame instanceof GW_SESSION_FINISHED_NTF ) { this . onSessionFinished ( frame ) ; } } private onSessionFinished ( frame ) { if ( frame . SessionID === this . _runningSession ) { this . _isRunning = false ; this . _runningSession = - 1 ; this . propertyChanged ( "IsRunning" ) ; } } } export class export class Scenes { private readonly _onChangedScenes = new TypedEvent < number > ( ) ; private readonly _onRemovedScenes = new TypedEvent < number > ( ) ; private readonly _onAddedScenes = new TypedEvent < number > ( ) ; type { Scene [ ] } memberof public readonly Scenes : Scene [ ] = [ ] ; private constructor ( readonly Connection ) { } static param { IConnection } Connection returns { Promise < Scenes > } memberof static async createScenesAsync ( Connection ) { try { const result = new Scenes ( Connection ) ; await result . refreshScenesAsync ( ) ; return result ; } catch ( error ) { return Promise . reject ( error ) ; } } private _notificationHandler : Disposable | undefined ; public async refreshScenesAsync ( ) { let dispose ; const newScenes = [ ] ; try { const notificationHandlerSceneList = new Promise < void > ( ( resolve , reject ) => { try { dispose = this . Connection . on ( frame => { if ( frame instanceof GW_GET_SCENE_LIST_NTF ) { frame . Scenes . forEach ( scene => { if ( typeof this . Scenes [ scene . SceneID ] === "undefined" ) { const newScene = new Scene ( this . Connection , scene . SceneID , scene . Name ) ; this . Scenes [ scene . SceneID ] = newScene ; newScenes . push ( newScene ) ; } } ) ; if ( frame . NumberOfRemainingScenes === 0 ) { if ( dispose ) { dispose . dispose ( ) ; } resolve ( ) ; } } } , [ GatewayCommand . GW_GET_SCENE_LIST_NTF ] ) ; } catch ( error ) { if ( dispose ) { dispose . dispose ( ) ; } reject ( error ) ; } } ) ; const getSceneListConfirmation = await this . Connection . sendFrameAsync ( new GW_GET_SCENE_LIST_REQ ( ) ) as GW_GET_SCENE_LIST_CFM ; if ( getSceneListConfirmation . NumberOfScenes > 0 ) { await notificationHandlerSceneList ; } else { if ( dispose ) { dispose . dispose ( ) ; } } for ( const scene of this . Scenes ) { if ( typeof scene !== "undefined" ) { await scene . refreshAsync ( ) ; } } for ( const scene of newScenes ) { this . notifyAddedScene ( scene . SceneID ) ; } if ( typeof this . _notificationHandler === "undefined" ) { this . _notificationHandler = this . Connection . on ( frame => this . onNotificationHandler ( frame ) , [ GatewayCommand . GW_SCENE_INFORMATION_CHANGED_NTF ] ) ; } return Promise . resolve ( ) ; } catch ( error ) { if ( dispose ) { dispose . dispose ( ) ; } return Promise . reject ( error ) ; } } private onNotificationHandler ( frame ) { if ( frame instanceof GW_SCENE_INFORMATION_CHANGED_NTF ) { switch ( frame . SceneChangeType ) { case SceneChangeType . Deleted : delete this . Scenes [ frame . SceneID ] ; this . notifyRemovedScene ( frame . SceneID ) ; break ; case SceneChangeType . Modified : this . Scenes [ frame . SceneID ] . refreshAsync ( ) . then ( ( ) => this . notifyChangedScene ( frame . SceneID ) ) . catch ( reason => { throw reason ; } ) ; default : break ; } } } param { Listener < number > } handler returns { Disposable } memberof public onChangedScene ( handler ) { return this . _onChangedScenes . on ( handler ) ; } param { Listener < number > } handler returns { Disposable } memberof public onRemovedScene ( handler ) { return this . _onRemovedScenes . on ( handler ) ; } param { Listener < number > } handler returns { Disposable } memberof public onAddedScene ( handler ) { return this . _onAddedScenes . on ( handler ) ; } private notifyChangedScene ( sceneId ) { this . _onChangedScenes . emit ( sceneId ) ; } private notifyRemovedScene ( sceneId ) { this . _onRemovedScenes . emit ( sceneId ) ; } private notifyAddedScene ( sceneId ) { this . _onAddedScenes . emit ( sceneId ) ; } param { string } sceneName returns { ( Scene | undefined ) } memberof public findByName ( sceneName ) { return this . Scenes . find ( sc => typeof sc !== "undefined" && sc . SceneName === sceneName ) ; } }