diff --git a/App.xaml b/App.xaml new file mode 100644 index 0000000..6169e24 --- /dev/null +++ b/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/App.xaml.cs b/App.xaml.cs new file mode 100644 index 0000000..29dd533 --- /dev/null +++ b/App.xaml.cs @@ -0,0 +1,14 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace FAtoPA +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } + +} diff --git a/AssemblyInfo.cs b/AssemblyInfo.cs new file mode 100644 index 0000000..b0ec827 --- /dev/null +++ b/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..8ac596f --- /dev/null +++ b/Config.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Threading.Tasks; + +namespace FAtoPA +{ + class Config + { + // FSM settings + public byte FSM_NetGroup { get; set; } = 1; + public byte FSM_NetNode { get; set; } = 1; + public byte FSM_PNA { get; set; } = 1; + public String FSM_LocalIP { get; set; } = "0.0.0.0"; + public bool FSM_UseMulticast { get; set; } = true; + public String FSM_MulticastIP { get; set; } = "239.192.0.1"; + public UInt16 FSM_MulticastPort { get; set; } = 25000; + + public UInt16 Modbus_ListenPort { get; set; } = 502; + public byte Modbus_DeviceID { get; set; } = 1; + public UInt16 Modbus_MaxRegister { get; set; } = 2000; + + public String VX_TargetIP { get; set; } = "192.168.14.1"; + public UInt16 VX_TargetPort { get; set; } = 5000; + + public Config() { + String _configpath = GetConfigPath(); + if (File.Exists(_configpath)) { + // Load Config + if (Load()) + { + // do nothing + + } else + { + // save default config + Save(); + } + } else + { + // save default config + Save(); + } + } + + public bool Save() + { + String _configPath = GetConfigPath(); + + try + { + String jsonstring = JsonSerializer.Serialize(this); + File.WriteAllText(_configPath, jsonstring); + Console.WriteLine("Config saved to [" + _configPath+"]"); + return true; + } + catch (Exception ex) + { + Console.Out.WriteLine("Config Save to ["+_configPath+"] Error: " + ex.Message); + } + return false; + } + + public bool Load() + { + String _configPath = GetConfigPath(); + + if (File.Exists(_configPath)) + { + try + { + string jsonstring = File.ReadAllText(_configPath); + Config? _loaded = JsonSerializer.Deserialize(jsonstring); + if (_loaded != null) + { + this.FSM_NetGroup = _loaded.FSM_NetGroup; + this.FSM_NetNode = _loaded.FSM_NetNode; + this.FSM_PNA = _loaded.FSM_PNA; + this.FSM_LocalIP = _loaded.FSM_LocalIP; + this.FSM_UseMulticast = _loaded.FSM_UseMulticast; + this.FSM_MulticastIP = _loaded.FSM_MulticastIP; + this.FSM_MulticastPort = _loaded.FSM_MulticastPort; + this.Modbus_ListenPort = _loaded.Modbus_ListenPort; + this.Modbus_DeviceID = _loaded.Modbus_DeviceID; + this.Modbus_MaxRegister = _loaded.Modbus_MaxRegister; + this.VX_TargetIP = _loaded.VX_TargetIP; + this.VX_TargetPort = _loaded.VX_TargetPort; + + Console.Out.WriteLine("Config Loaded from [" + _configPath + "]"); + return true; + } else Console.Out.WriteLine("Config Load Error: File ["+ _configPath + "] is not valid Config."); + } catch(Exception ex) + { + Console.Out.WriteLine("Config Load from ["+_configPath+"] Error: " + ex.Message); + } + } + else Console.Out.WriteLine("Config Load Error: File ["+ _configPath + "] not found."); + return false; + } + + private static String GetConfigPath() + { + String _configPath = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FAtoPA"); + _configPath = System.IO.Path.Combine(_configPath, "config.json"); + return _configPath; + } + } +} diff --git a/Database.cs b/Database.cs new file mode 100644 index 0000000..7acedb0 --- /dev/null +++ b/Database.cs @@ -0,0 +1,475 @@ +using Microsoft.Data.Sqlite; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FAtoPA +{ + class Database + { + String connectionString = "Data Source=database.db"; + + /// + /// Create Database Object + /// + public Database() + { + + CreateFSMTable(); + CreateModbusTable(); + CreateVXTable(); + } + + private bool CreateFSMTable() + { + //Debug.WriteLine("About to execute CreateFSMTable"); + using (var connection = new SqliteConnection(connectionString)) + { + try + { + connection.Open(); + var createtablecmd = connection.CreateCommand(); + createtablecmd.CommandText = "CREATE TABLE IF NOT EXISTS FsmData (SIID TEXT PRIMARY KEY, Enable INTEGER, Description TEXT)"; + createtablecmd.ExecuteNonQuery(); + Debug.WriteLine("CreateFSMTable success"); + return true; + } + catch (Exception ex) + { + Debug.WriteLine("Error CreateFSMTable, Exception : " + ex.Message); + return false; + } + + } + } + + public bool ClearFSMTable() { + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + var deleteCmd = connection.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM FsmData"; + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting FSMData: " + e.Message); + } + } + return false; + } + + public List GetFSMDatas() + { + List fsmDatas = new List(); + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + + var selectCmd = connection.CreateCommand(); + selectCmd.CommandText = "SELECT * FROM FsmData"; + using (var reader = selectCmd.ExecuteReader()) + { + while (reader.Read()) + { + FSMData fsmData = new FSMData(reader.GetString(0), reader.GetBoolean(1), reader.GetString(2)); + fsmDatas.Add(fsmData); + } + } + } + return fsmDatas; + } + + public bool AddFSMData(params FSMData[] data) + { + using(var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + foreach (var item in data) + { + var insertCmd = connection.CreateCommand(); + insertCmd.CommandText = "INSERT INTO FsmData (SIID, Enable, Description) VALUES (@SIID, @Enable, @Description)"; + insertCmd.Parameters.AddWithValue("@SIID", item.SIID); + insertCmd.Parameters.AddWithValue("@Enable", item.Enable); + insertCmd.Parameters.AddWithValue("@Description", item.Description); + try + { + int result = insertCmd.ExecuteNonQuery(); + if (result <= 0) + { + transaction.Rollback(); + return false; + } + } + catch (SqliteException e) + { + Debug.WriteLine("Error inserting FSMData: " + e.Message); + transaction.Rollback(); + return false; + } + } + transaction.Commit(); + } + return true; + } + } + + public bool RemoveFSMDatabySIID(String SIID) + { + using (var conn = new SqliteConnection(connectionString)) + { + conn.Open(); + var deleteCmd = conn.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM FsmData WHERE SIID = @SIID"; + deleteCmd.Parameters.AddWithValue("@SIID", SIID); + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting FSMData: " + e.Message); + return false; + } + } + } + + private bool CreateModbusTable() + { + //Debug.WriteLine("About to execute CreateModbusTable"); + using (var connection = new SqliteConnection(connectionString)) + { + try + { + connection.Open(); + var modbuscmd = connection.CreateCommand(); + modbuscmd.CommandText = "CREATE TABLE IF NOT EXISTS ModbusData (SIID TEXT PRIMARY KEY, Register INTEGER, Description TEXT)"; + modbuscmd.ExecuteNonQuery(); + Debug.WriteLine("CreateModbusTable success"); + return true; + } + catch (Exception ex) + { + Debug.WriteLine("Error CreateModbusTable, Exception : " + ex.Message); + return false; + } + } + } + + public bool ClearModbusTable() + { + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + var deleteCmd = connection.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM ModbusData"; + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting ModbusData: " + e.Message); + } + } + return false; + } + + public Boolean AddModbusData(params ModbusData[] data) + { + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + foreach (var item in data) + { + var insertCmd = connection.CreateCommand(); + insertCmd.CommandText = "INSERT INTO ModbusData (SIID, Register, Description) VALUES (@SIID, @Register, @Description)"; + insertCmd.Parameters.AddWithValue("@SIID", item.SIID); + insertCmd.Parameters.AddWithValue("@Register", item.Register); + insertCmd.Parameters.AddWithValue("@Description", item.Description); + try + { + int result = insertCmd.ExecuteNonQuery(); + if (result <= 0) + { + transaction.Rollback(); + return false; + } + } + catch (SqliteException e) + { + Debug.WriteLine("Error inserting ModbusData: " + e.Message); + transaction.Rollback(); + return false; + } + } + transaction.Commit(); + } + return true; + } + } + + public List GetModbusDatas() + { + List modbusDatas = new List(); + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + + var selectCmd = connection.CreateCommand(); + selectCmd.CommandText = "SELECT * FROM ModbusData"; + using (var reader = selectCmd.ExecuteReader()) + { + while (reader.Read()) + { + ModbusData modbusdata = new ModbusData(reader.GetString(0), reader.GetFieldValue(1), reader.GetString(2)); + modbusDatas.Add(modbusdata); + } + } + } + return modbusDatas; + } + + public bool RemoveModbusDatabySIID(String SIID) + { + using (var conn = new SqliteConnection(connectionString)) + { + conn.Open(); + var deleteCmd = conn.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM ModbusData WHERE SIID = @SIID"; + deleteCmd.Parameters.AddWithValue("@SIID", SIID); + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting ModbusData: " + e.Message); + return false; + } + } + } + + private bool CreateVXTable() + { + //Debug.WriteLine("About to execute CreateVXTable"); + using (var connection = new SqliteConnection(connectionString)) + { + try + { + connection.Open(); + var vxlancmd = connection.CreateCommand(); + vxlancmd.CommandText = "CREATE TABLE IF NOT EXISTS VxTable (SIID TEXT PRIMARY KEY, FrameID INTEGER, CIN INTEGER, Description TEXT)"; + vxlancmd.ExecuteNonQuery(); + Debug.WriteLine("CreateVXTable success"); + return true; + } + catch (Exception ex) + { + Debug.WriteLine("Error CreateVXTable, Exception : " + ex.Message); + return false; + } + } + } + + public bool ClearVXTable() + { + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + var deleteCmd = connection.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM VxTable"; + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting VXData: " + e.Message); + } + } + return false; + } + + public List GetVXDatas() + { + List vxDatas = new List(); + using (var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + + var selectCmd = connection.CreateCommand(); + selectCmd.CommandText = "SELECT * FROM VxTable"; + using (var reader = selectCmd.ExecuteReader()) + { + while (reader.Read()) + { + VXData vxdata = new VXData(reader.GetString(0), reader.GetByte(1), reader.GetByte(2)); + vxDatas.Add(vxdata); + } + } + } + return vxDatas; + } + + public bool RemoveVXDatabySIID(String SIID) + { + using (var conn = new SqliteConnection(connectionString)) + { + conn.Open(); + var deleteCmd = conn.CreateCommand(); + deleteCmd.CommandText = "DELETE FROM VxTable WHERE SIID = @SIID"; + deleteCmd.Parameters.AddWithValue("@SIID", SIID); + try + { + int result = deleteCmd.ExecuteNonQuery(); + return (result > 0); + } + catch (SqliteException e) + { + Debug.WriteLine("Error deleting VXData: " + e.Message); + return false; + } + } + } + + public bool AddVXData(params VXData[] data) { + using(var connection = new SqliteConnection(connectionString)) + { + connection.Open(); + using (var transaction = connection.BeginTransaction()) + { + foreach (var item in data) + { + var insertCmd = connection.CreateCommand(); + insertCmd.CommandText = "INSERT INTO VxTable (SIID, FrameID, CIN, Description) VALUES (@SIID, @FrameID, @CIN, @Description)"; + insertCmd.Parameters.AddWithValue("@SIID", item.SIID); + insertCmd.Parameters.AddWithValue("@FrameID", item.FrameID); + insertCmd.Parameters.AddWithValue("@CIN", item.CIN); + insertCmd.Parameters.AddWithValue("@Description", item.Description); + try + { + int result = insertCmd.ExecuteNonQuery(); + if (result <= 0) + { + transaction.Rollback(); + return false; + } + } + catch (SqliteException e) + { + Debug.WriteLine("Error inserting VXData: " + e.Message); + transaction.Rollback(); + return false; + } + } + transaction.Commit(); + } + return true; + } + } + + } + + class FSMData + { + public String SIID { get; set; } + public Boolean Enable { get; set; } + public String Description { get; set; } + public String Value { get; set; } + public String LastUpdate { get; set; } + public FSMData(String siid, Boolean enable, String description) + { + this.SIID = siid; + this.Enable = enable; + this.Description = description; + this.Value = ""; + this.LastUpdate = ""; + } + public FSMData(String siid) + { + this.SIID = siid; + this.Enable = true; + this.Description = ""; + this.Value = ""; + this.LastUpdate = ""; + } + public FSMData(String siid, Boolean enable) + { + this.SIID = siid; + this.Enable = enable; + this.Description = ""; + this.LastUpdate = ""; + this.Value = ""; + + } + } + + class ModbusData + { + public String SIID { get; set; } + public UInt16 Register { get; set; } + public String Description { get; set; } + + public String Value { get; set; } + public String LastUpdate { get; set; } + public ModbusData(String siid, UInt16 register, String description) + { + this.SIID = siid; + this.Register = register; + this.Description = description; + this.Value = ""; + this.LastUpdate = ""; + } + public ModbusData(String siid, UInt16 register) + { + this.SIID = siid; + this.Register = register; + this.Description = siid + " To " + register; + this.Value = ""; + this.LastUpdate = ""; + } + } + + class VXData + { + public String SIID { get; set; } + public Byte FrameID { get; set; } + public Byte CIN { get; set; } + public String Description { get; set; } + public String Value { get; set; } + public String LastUpdate { get; set; } + public VXData(String siid, Byte frameid, Byte cin, String Description) + { + this.SIID = siid; + this.FrameID = frameid; + this.CIN = cin; + this.Description=Description; + this.Value = ""; + this.LastUpdate = ""; + } + public VXData(String siid, Byte frameid, Byte cin) + { + this.SIID = siid; + this.FrameID = frameid; + this.CIN = cin; + this.Description = siid+" To "+ frameid + "." + cin; + this.Value = ""; + this.LastUpdate = ""; + } + } +} diff --git a/EventInterface.cs b/EventInterface.cs new file mode 100644 index 0000000..b2ef6b0 --- /dev/null +++ b/EventInterface.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FAtoPA +{ + interface EventInterface + { + void ConnectStatus(bool success, String message); + void StatisticUpdate(uint TXOK, uint RXOK, uint TXErr, uint RXerr, uint TXBytes, uint RXBytes); + void Log(String msg); + } +} diff --git a/FAtoPA.csproj b/FAtoPA.csproj new file mode 100644 index 0000000..1d14fef --- /dev/null +++ b/FAtoPA.csproj @@ -0,0 +1,56 @@ + + + + WinExe + net8.0-windows10.0.26100.0 + enable + enable + true + AnyCPU;x64 + + + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\ApplicationProtocolCIL.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\Backend.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\DataExchangeInterfaces.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\FSIConfig.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\FSITrace.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\FSM5000FSI.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\FSM5000FSIAPI.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\FSM5000FSILoader.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\MPNetCIL.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\MPNetGate.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\Repository.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\StandardCIL.dll + + + + + + + + + diff --git a/FAtoPA.sln b/FAtoPA.sln new file mode 100644 index 0000000..f4d3680 --- /dev/null +++ b/FAtoPA.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.35027.167 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FAtoPA", "FAtoPA.csproj", "{28C460C4-E551-4653-AB20-99A9D1A1FFCB}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Debug|x64.ActiveCfg = Debug|x64 + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Debug|x64.Build.0 = Debug|x64 + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Release|Any CPU.Build.0 = Release|Any CPU + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Release|x64.ActiveCfg = Release|x64 + {28C460C4-E551-4653-AB20-99A9D1A1FFCB}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F6A7288A-9F10-4AB3-8A26-9B933C1AF4EB} + EndGlobalSection +EndGlobal diff --git a/FSM.cs b/FSM.cs new file mode 100644 index 0000000..fafdda1 --- /dev/null +++ b/FSM.cs @@ -0,0 +1,280 @@ +using FSM5000FSI; +using FSM5000FSIAPI.Version3; + +using System; +using System.CodeDom; +using System.Collections.Generic; +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; + controller = FSIController.GetInstance(); + 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) + { + byte[] defaultip = new byte[] { 239, 192, 0, 1 }; + ushort defaultport = 25000; + + AdvancedFSIConfig advancedFSIConfig = new AdvancedFSIConfig(); + advancedFSIConfig.IsIPMulticast = useMulticast; + if (useMulticast) + { + if (MulticastIP != null && MulticastIP.Length == 4) + advancedFSIConfig.MulticastAddress = MulticastIP; + else + advancedFSIConfig.MulticastAddress = defaultip; + + if (PortNumber>1 && PortNumber<65535) + advancedFSIConfig.PortNumber = PortNumber; + else + advancedFSIConfig.PortNumber = defaultport; + } + + advancedFSIConfig.NetstackTraceLevel = SourceLevels.Error; + + if (config!=null) config.AdvancedFSIConfig = advancedFSIConfig; + } + + + /// + /// Start FSM Monitoring + /// + public void Start() + { + // 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); + Console.WriteLine("[FSM] Start result = "+result.ToString()); + } + + public void AddListener(FSMResultInterface listener) + { + if (listenerlist != null) listenerlist.Add(listener); + } + + /// + /// Stop FSM Monitoring + /// + public void Stop() + { + if (controller != null) + { + try + { + //TODO : somehow bikin crash terus + //Result result = controller.Shutdown(); + //Console.WriteLine("[FSM] Shutdown result = " + result.ToString()); + } catch (Exception e) + { + Console.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) + { + if (type_dictionary != null) + { + int type = int.Parse(devItemType.FunctionalType.ToString()); + if (!type_dictionary.ContainsKey(type)) type_dictionary.Add(type, devItemType.Description); + + } + Console.Out.WriteLine("Item type " + devItemType.FunctionalType + " (" + devItemType.Description + ")"); + } + + /// + /// Akan muncul di urutan kedua, untuk informasi node device apa saja yang terdeteksi di system + /// + /// + public void SetItem(Item devItem) + { + 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); + // notify all listeners + if (listeners != null) + foreach (var item in listeners) + item.DiscoveredSIID(SIID, nodeData); + + } + } + Console.Out.WriteLine("Item (" + devItem.SIID + ", " + devItem.FunctionalType + " (" + devItem.Label + ")"); + } + + /// + /// Akan muncul kalau suatu node hilang dari system + /// + /// + public void RemoveItem(SIID address) + { + if (node_data != null) + { + String SIID = address.ToString(); + if (node_data.ContainsKey(SIID)) node_data.Remove(SIID); + + } + Console.Out.WriteLine("SI " + address + " removed."); + } + } + + /// + /// 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) + { + if (node_data != null) + { + String SIID = devItemState.SIID.ToString(); + NodeData nd = node_data[SIID]; + if (nd != null) + { + NodeState? prev = nd.State; + nd.State = new NodeState(devItemState); + + // notify all listeners + if (listeners != null) + foreach (var item in listeners) + item.NewState(SIID, prev, nd.State); + + if (prev != null) + { + Console.WriteLine("SIID="+SIID+" Change LogicalState from "+prev.LogicalState+" to "+nd.State.LogicalState); + } else + { + Console.Out.WriteLine("New State for SIID=" + SIID + " LogicalState=" + nd.State.LogicalState); + } + } + } + //Console.Out.WriteLine("State " + devItemState.SIID + " = " + devItemState.LogicalState); + + } + + /// + /// Akan muncul sekali di awal mula, sebagai informasi waktu di panel system + /// + /// + public void SetMPNetTime(DateTime mpNetTime) + { + Console.Out.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) Console.Out.Write(message); + } + + public override void WriteLine(string? message) + { + if (message != null && message.Length > 0) Console.Out.WriteLine(message); + } + } + +} diff --git a/FSMResultInterface.cs b/FSMResultInterface.cs new file mode 100644 index 0000000..fce8ff1 --- /dev/null +++ b/FSMResultInterface.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace FAtoPA +{ + interface FSMResultInterface + { + void DiscoveredSIID(String SIID, NodeData type); + void NewState(String SIID, NodeState? previous, NodeState current); + } +} diff --git a/MainWindow.xaml b/MainWindow.xaml new file mode 100644 index 0000000..66172f2 --- /dev/null +++ b/MainWindow.xaml @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +