Files
FAtoPA.Net/FSM.cs
2024-11-21 16:33:25 +07:00

296 lines
11 KiB
C#

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<FSMResultInterface> listenerlist;
public Dictionary<int, String> ItemTypeDictionary { get; }
public Dictionary<String, NodeData> AvailableNodes { get; }
private EventInterface _event;
public FSM(EventInterface callback)
{
_event = callback;
ItemTypeDictionary = new Dictionary<int, string>();
AvailableNodes = new Dictionary<String, NodeData>();
listenerlist = new List<FSMResultInterface>();
}
/// <summary>
/// Initialize Fire Alarm Module
/// </summary>
/// <param name="netgroup">1 - 255</param>
/// <param name="netnode">1 - 255</param>
/// <param name="pna">1 - 255</param>
/// <param name="localip">on a system with multiple network adapter, use this to specify which adapter will be used</param>
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";
}
/// <summary>
/// Optional option if using Multicast Communication
/// </summary>
/// <param name="useMulticast">true if want to use Multicast</param>
/// <param name="MulticastIP">target Multicast IP, if not available, default to 239.192.0.1</param>
/// <param name="PortNumber">target Port, if not available, default to 25000</param>
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;
}
}
/// <summary>
/// Start FSM Monitoring
/// </summary>
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);
}
/// <summary>
/// Stop FSM Monitoring
/// </summary>
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);
}
}
}
}
/// <summary>
/// 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.
/// </summary>
class ConfigListener : IPanelConfigListener
{
private Dictionary<int, String> type_dictionary;
private Dictionary<String, NodeData> node_data;
private List<FSMResultInterface> listeners;
public ConfigListener(Dictionary<int, String> type, Dictionary<String, NodeData> data, List<FSMResultInterface> listener)
{
this.type_dictionary = type;
this.node_data = data;
this.listeners = listener;
}
/// <summary>
/// Akan muncul di pertama kali, untuk informasi bahwa device dengan FunctionalType [X} memiliki deskripsi [Y]
/// </summary>
/// <param name="devItemType"></param>
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}");
}
}
/// <summary>
/// Akan muncul di urutan kedua, untuk informasi node device apa saja yang terdeteksi di system
/// </summary>
/// <param name="devItem"></param>
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}");
}
}
/// <summary>
/// Akan muncul kalau suatu node hilang dari system
/// </summary>
/// <param name="address"></param>
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);
}
}
}
/// <summary>
/// The State Listener receive all states for devices send by the panel network.
/// Ini yang paling penting, untuk trigger ke Modbus dan VX3000
/// </summary>
class StateListener : IStateListener
{
private Dictionary<String,NodeData> node_data;
private List<FSMResultInterface> listeners;
public StateListener(Dictionary<String,NodeData> data, List<FSMResultInterface> listener)
{
this.node_data= data;
this.listeners = listener;
}
/// <summary>
/// Akan muncul ketiga dan seterusnya, ketika ada perubahan status dari node device
/// </summary>
/// <param name="devItemState"></param>
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");
}
/// <summary>
/// Akan muncul sekali di awal mula, sebagai informasi waktu di panel system
/// </summary>
/// <param name="mpNetTime"></param>
public void SetMPNetTime(DateTime mpNetTime)
{
Debug.WriteLine($"Time is {mpNetTime}");
}
}
/// <summary>
/// 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
/// </summary>
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);
}
}
}