using FSM5000FSI; using FSM5000FSIAPI.Version3; using System; using System.CodeDom; using System.Collections.Generic; using System.Data.Entity.Infrastructure.Interception; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading.Tasks; namespace FAtoPA { class FSM { public static bool Started = false; private FSIConfig config; private FSIController controller; private List listenerlist; public Dictionary ItemTypeDictionary { get; } public Dictionary AvailableNodes { get; } private EventInterface _event; public FSM(EventInterface callback) { _event = callback; ItemTypeDictionary = new Dictionary(); AvailableNodes = new Dictionary(); listenerlist = new List(); } /// /// Initialize Fire Alarm Module /// /// 1 - 255 /// 1 - 255 /// 1 - 255 /// on a system with multiple network adapter, use this to specify which adapter will be used public FSM(EventInterface callback, byte netgroup, byte netnode, byte pna, byte[] localip) : this(callback) { SetConfig(netgroup, netnode, pna, localip); } public void SetConfig(byte netgroup, byte netnode, byte pna, byte[] localip) { config = new FSIConfig(); config.MPNetGroup = netgroup; config.MPNetNode = netnode; config.PNA = pna; config.LocalIPAddress = localip; config.RepositoryLocation = ".\\repository"; } /// /// Optional option if using Multicast Communication /// /// true if want to use Multicast /// target Multicast IP, if not available, default to 239.192.0.1 /// target Port, if not available, default to 25000 public void MulticastConfig(Boolean useMulticast, byte[] MulticastIP, ushort PortNumber) { if (config != null) { if (config.AdvancedFSIConfig == null) config.AdvancedFSIConfig = new AdvancedFSIConfig(); config.AdvancedFSIConfig.IsIPMulticast = useMulticast; config.AdvancedFSIConfig.MulticastAddress = MulticastIP; config.AdvancedFSIConfig.PortNumber = PortNumber; config.AdvancedFSIConfig.NetstackTraceLevel = SourceLevels.Error; } } /// /// Start FSM Monitoring /// public void Start() { controller = FSIController.GetInstance(); // internal Listeners controller.AddListener(new ConfigListener(ItemTypeDictionary, AvailableNodes, listenerlist)); controller.AddListener(new StateListener(AvailableNodes, listenerlist)); TraceConsoleWritter outputter = new TraceConsoleWritter(); controller.SetTraceLevel(SourceLevels.Warning); //for support issues please set the level to SourceLevels.Verbose Result result = controller.Startup(config); Debug.WriteLine("[FSM] Start result = "+result.ToString()); if (result==Result.SUCCESS) { Started = true; if (_event != null) _event.ConnectStatus(true, "FSM Started"); } else { Started = false; if (_event != null) _event.ConnectStatus(false, "FSM Failed to Start"); } } public void AddListener(FSMResultInterface listener) { if (listenerlist != null) listenerlist.Add(listener); } /// /// Stop FSM Monitoring /// public void Stop() { if (controller != null) { try { Result result = controller.Shutdown(); Debug.WriteLine("[FSM] Shutdown result = " + result.ToString()); if (_event!=null) _event.ConnectStatus(false, "FSM Stopped"); } catch (Exception e) { Debug.WriteLine("[FSM] Error on Stop: " + e.Message); } } } } /// /// The Config Listener receives all information about the configuration /// received from the panel network. The information must be stored in real application /// to know the devices from the panel network and the possible commands. /// class ConfigListener : IPanelConfigListener { private Dictionary type_dictionary; private Dictionary node_data; private List listeners; public ConfigListener(Dictionary type, Dictionary data, List listener) { this.type_dictionary = type; this.node_data = data; this.listeners = listener; } /// /// Akan muncul di pertama kali, untuk informasi bahwa device dengan FunctionalType [X} memiliki deskripsi [Y] /// /// public void SetItemType(ItemType devItemType) { //Debug.WriteLine($"Item type {devItemType.FunctionalType} ({devItemType.Description})"); if (type_dictionary != null) { int type = int.Parse(devItemType.FunctionalType.ToString()); if (!type_dictionary.ContainsKey(type)) { Debug.WriteLine($"Adding key={type}, value={devItemType.Description} to type_dictionary"); type_dictionary.Add(type, devItemType.Description); } else Debug.WriteLine($"type_dictionary already have key={type}"); } } /// /// Akan muncul di urutan kedua, untuk informasi node device apa saja yang terdeteksi di system /// /// public void SetItem(Item devItem) { Debug.WriteLine($"Item ({devItem.SIID}, {devItem.FunctionalType} ({devItem.Label})"); if (node_data != null) { String SIID = devItem.SIID.ToString(); int type = int.Parse(devItem.FunctionalType.ToString()); if (!node_data.ContainsKey(SIID)) { NodeData nodeData = new NodeData(); nodeData.SIID = devItem.SIID; nodeData.Type = type; nodeData.Label = devItem.Label; nodeData.Description = type_dictionary.ContainsKey(type) ? type_dictionary[type] : "Unknown"; node_data.Add(SIID, nodeData); Debug.WriteLine($"Adding SIID={nodeData.SIID} Label={nodeData.Label} Description={nodeData.Description} to node_data"); // notify all listeners if (listeners != null) foreach (var item in listeners) item.DiscoveredSIID(SIID, nodeData); } else Debug.WriteLine($"node_data already have SIID={SIID}"); } } /// /// Akan muncul kalau suatu node hilang dari system /// /// public void RemoveItem(SIID address) { Debug.WriteLine("SI " + address + " removed."); if (node_data != null) { String SIID = address.ToString(); if (node_data.ContainsKey(SIID)) node_data.Remove(SIID); } } } /// /// The State Listener receive all states for devices send by the panel network. /// Ini yang paling penting, untuk trigger ke Modbus dan VX3000 /// class StateListener : IStateListener { private Dictionary node_data; private List listeners; public StateListener(Dictionary data, List listener) { this.node_data= data; this.listeners = listener; } /// /// Akan muncul ketiga dan seterusnya, ketika ada perubahan status dari node device /// /// public void SetItemState(ItemState devItemState) { Debug.WriteLine($"State {devItemState.SIID} = {devItemState.LogicalState}"); if (node_data != null) { String SIID = devItemState.SIID.ToString(); if (node_data.ContainsKey(SIID)) { NodeData nd = node_data[SIID]; if (nd != null) { NodeState prev = nd.State; nd.State = new NodeState(devItemState); //if (prev != null) //{ // Debug.WriteLine($"SIID={SIID} Change LogicalState from {prev.LogicalState} to {nd.State.LogicalState}"); //} //else //{ // Debug.WriteLine($"SIID={SIID} New LogicalState {nd.State.LogicalState}"); //} // notify all listeners if (listeners != null) foreach (var item in listeners) item.NewState(SIID, prev, nd.State); } else Debug.WriteLine($"NodeData with SIID {SIID} is null"); } else Debug.WriteLine($"node_data doesn't contain SIID {SIID}"); } else Debug.WriteLine("node_data is null"); } /// /// Akan muncul sekali di awal mula, sebagai informasi waktu di panel system /// /// public void SetMPNetTime(DateTime mpNetTime) { Debug.WriteLine($"Time is {mpNetTime}"); } } /// /// Receive the traces from the FSI and output the traces to console /// In real application it is very useful to write the traces to files /// for suppport issues /// class TraceConsoleWritter : TraceListener { public override void Write(string message) { if (message!=null && message.Length>0) Debug.WriteLine(message); } public override void WriteLine(string message) { if (message != null && message.Length > 0) Debug.WriteLine(message); } } }