/*-------------------------------------------------------------------------------------------------------------- * Copyright (c) insite-gmbh. All rights reserved. * Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------------------------*/ import { Subject } from "rxjs/Subject"; import { Observable } from 'rxjs/Rx'; import { PropertyChangeEvent, IScriptEventProxy, MethodPropertyChangeEvent } from "../domain"; import { CallerInfo } from './../domain/propertyChangedEvent'; //================================================================================================================================== /** * This stores the Subscriber information and the subject to execute the callback on the subscriber * @class PlcSubscriber * @author insite-gmbh */ class ScriptEventProxy implements IScriptEventProxy { /** * */ constructor(private _cleanup: (instance: IScriptEventProxy) => void) { if (_cleanup == null) throw "cleanup delegate is null!" } Id: string = null; /** * * * @property ScritpUnit * @type {string} */ ScriptUnit: string; /** * * * @property Functionname * @type {string} */ Functionname: string = null; /** * * * @property Subject * @type {Subject} */ Subject: Subject; LastError: any = null; /** * You can call subscribe on this property to get informed for updates. * * @property ChangeEvent * @type {Observable} */ get ChangeEvent(): Observable { if (this.Subject == null) this.Subject = new Subject(); return this.Subject.asObservable(); } /** * unregister the variable on inax */ dispose() { if (this._cleanup != null) { this._cleanup(this); } } } //================================================================================================================================== /** * This class handles the proxy generation for the plc signalR hub * @class PlcMappingPack * @author insite-gmbh */ export class ScriptEventProxyFactory { /** * This holds the list of proxies for change events * * @property _proxies * @type {Array} * @private */ private _proxies = new Array(); /** * This holds the instance of the plc hub proxy. * * @property _hubProxy * @type {any} * @private */ public constructor(private _hubProxy: any) { if (_hubProxy == null) throw "scriptHubProxy is null!"; this._hubProxy.on("scriptPropertiesChanged", (scriptUnit: string, propertyNames: Array, propertyValues: Array) => { let dce = new PropertyChangeEvent(); dce.ScriptUnit = scriptUnit; dce.Properties = propertyNames; dce.Values = propertyValues; this._proxies.forEach(channelSub => { if (channelSub.ScriptUnit === scriptUnit) { channelSub.Subject.next(dce); } }); }); this._hubProxy.on("scriptPropertyChanged", (scriptUnit: string, propertyNames: string, propertyValue: any) => { let dce = new PropertyChangeEvent(); dce.ScriptUnit = scriptUnit; dce.Properties = [propertyNames]; dce.Values = [propertyValue]; this._proxies.forEach(channelSub => { if (channelSub.ScriptUnit === scriptUnit) { channelSub.Subject.next(dce); } }); }); this._hubProxy.on("scriptsInitialized", () => { }); } public create(scriptUnit: string, functionName: string = null): IScriptEventProxy { // Now we just create our internal object so we can track this subject // in case someone else wants it too let channelSub = new ScriptEventProxy((sub) => this.release(sub)); if (functionName != null) { channelSub.Id = scriptUnit + functionName + Date.now().toLocaleString(); channelSub.Functionname = functionName; } else { channelSub.Id = scriptUnit + Date.now().toLocaleString(); } channelSub.ScriptUnit = scriptUnit; channelSub.Subject = new Subject(); this._proxies.push(channelSub); return channelSub; } public setProperty(scriptUnit: string, propertyName: string, value: any): Observable{ let subject: Subject = new Subject(); this._hubProxy.invoke("SetScriptProperty", scriptUnit, propertyName, value) .done(() => { subject.next(true); subject.complete(); }) .fail((error: any) => { subject.next(false); subject.error(error); }); return subject.asObservable(); } public invoke(scriptUnit: string, functionName: string, parameters: Array, withCallback: boolean = false): Observable { let evProxy = withCallback ? this.create(scriptUnit, functionName) as ScriptEventProxy : null; let result = new Subject(); let observable = result.asObservable(); let callerInfo : CallerInfo = { ScriptUnit : scriptUnit, FunctionName: functionName, Parameters: parameters } if (evProxy != null) { evProxy.ChangeEvent.subscribe((event: PropertyChangeEvent) => { let res = new MethodPropertyChangeEvent(); res.CallerInfo = callerInfo; res.Event = event; result.next(res); }); } this._hubProxy.invoke("RunScript", scriptUnit, functionName, parameters) .done(() => { if (evProxy != null) evProxy.dispose(); let res = new MethodPropertyChangeEvent(); res.CallerInfo = callerInfo; res.IsFinished = true; result.next(res); result.complete(); }) .fail((error: any) => { if (evProxy != null) { evProxy.LastError = error; evProxy.dispose(); } let res = new MethodPropertyChangeEvent(); res.CallerInfo = callerInfo; res.IsFinished = true; res.Error = error; result.next(res); result.error(error); }); return observable; } private release(proxy: IScriptEventProxy): void { var channelSub = proxy as ScriptEventProxy; if (channelSub.LastError == null) channelSub.Subject.complete(); else channelSub.Subject.error(channelSub.LastError); let idx = this._proxies.indexOf(channelSub); if (idx != -1) this._proxies.splice(idx, 1); else { console.log(`Subscriber for scriptunit ${proxy.ScriptUnit} not found after unsubscribe!`); } } }