From 84885e5047b2700c34828a644f29d5bb82111fa5 Mon Sep 17 00:00:00 2001 From: rdkartono Date: Thu, 21 Nov 2024 13:51:18 +0700 Subject: [PATCH] Add project files. --- App.config | 22 + App.xaml | 9 + App.xaml.cs | 17 + Config.cs | 112 +++ Database.cs | 475 ++++++++++ EventInterface.cs | 15 + FAtoPA.Net.csproj | 207 +++++ FAtoPA.Net.sln | 28 + FSM.cs | 288 ++++++ FSMResultInterface.cs | 14 + MainWindow.xaml | 279 ++++++ MainWindow.xaml.cs | 1417 ++++++++++++++++++++++++++++++ MappingData.cs | 26 + ModbusSlave.cs | 545 ++++++++++++ NodeData.cs | 41 + Properties/AssemblyInfo.cs | 52 ++ Properties/Resources.Designer.cs | 71 ++ Properties/Resources.resx | 117 +++ Properties/Settings.Designer.cs | 30 + Properties/Settings.settings | 7 + VX3K.cs | 361 ++++++++ packages.config | 19 + 22 files changed, 4152 insertions(+) create mode 100644 App.config create mode 100644 App.xaml create mode 100644 App.xaml.cs create mode 100644 Config.cs create mode 100644 Database.cs create mode 100644 EventInterface.cs create mode 100644 FAtoPA.Net.csproj create mode 100644 FAtoPA.Net.sln create mode 100644 FSM.cs create mode 100644 FSMResultInterface.cs create mode 100644 MainWindow.xaml create mode 100644 MainWindow.xaml.cs create mode 100644 MappingData.cs create mode 100644 ModbusSlave.cs create mode 100644 NodeData.cs create mode 100644 Properties/AssemblyInfo.cs create mode 100644 Properties/Resources.Designer.cs create mode 100644 Properties/Resources.resx create mode 100644 Properties/Settings.Designer.cs create mode 100644 Properties/Settings.settings create mode 100644 VX3K.cs create mode 100644 packages.config diff --git a/App.config b/App.config new file mode 100644 index 0000000..816b022 --- /dev/null +++ b/App.config @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/App.xaml b/App.xaml new file mode 100644 index 0000000..40d34dc --- /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..3413eb6 --- /dev/null +++ b/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace FAtoPA.Net +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Config.cs b/Config.cs new file mode 100644 index 0000000..594adf5 --- /dev/null +++ b/Config.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +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; } = 2; + public byte FSM_NetNode { get; set; } = 1; + public byte FSM_PNA { get; set; } = 2; + public String FSM_LocalIP { get; set; } = "192.168.10.23"; + public bool FSM_UseMulticast { get; set; } = false; + 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; + private String _configpath = ""; + + public Config() { + _configpath = GetConfigPath(); + // kalau belum ada, create default + if (!File.Exists(_configpath)) Save(); + } + + public Boolean FileIsExist() { return File.Exists(_configpath); } + + public bool Save() + { + + Debug.WriteLine("Will Save Config to [" + _configpath + "]"); + + try + { + String jsonstring = JsonSerializer.Serialize(this); + File.WriteAllText(_configpath, jsonstring); + Debug.WriteLine("Config saved to [" + _configpath + "]"); + return true; + } + catch (Exception ex) + { + Debug.WriteLine("Config Save to ["+ _configpath + "] Error: " + ex.Message); + } + return false; + } + + public bool Load() + { + + 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; + + Debug.WriteLine("Config Loaded from [" + _configpath + "]"); + return true; + } else Debug.WriteLine("Config Load Error: File ["+ _configpath + "] is not valid Config."); + } catch(Exception ex) + { + Debug.WriteLine("Config Load from ["+ _configpath + "] Error: " + ex.Message); + } + } + else Debug.WriteLine("Config Load Error: File ["+ _configpath + "] not found."); + return false; + } + + private static String GetConfigPath() + { + String _xx = System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "FAtoPA"); + Debug.WriteLine("Config Path: " + _xx); + if (!Directory.Exists(_xx)) { + try + { + Directory.CreateDirectory(_xx); + } + catch (Exception ex) + { + Debug.WriteLine("Config Path Error: " + ex.Message); + } + } + + return System.IO.Path.Combine(_xx, "config.json"); + } + } +} 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.Net.csproj b/FAtoPA.Net.csproj new file mode 100644 index 0000000..cb23295 --- /dev/null +++ b/FAtoPA.Net.csproj @@ -0,0 +1,207 @@ + + + + + Debug + AnyCPU + {C158634C-A54E-41CD-A41A-6D0AFF841BE4} + WinExe + FAtoPA.Net + FAtoPA.Net + v4.8 + 512 + {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 4 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + bin\x64\Debug\ + DEBUG;TRACE + full + x64 + 7.3 + prompt + true + + + bin\x64\Release\ + TRACE + true + pdbonly + x64 + 7.3 + prompt + true + + + + ..\..\..\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 + + + packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + packages\Microsoft.Data.Sqlite.Core.9.0.0\lib\netstandard2.0\Microsoft.Data.Sqlite.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 + + + packages\SQLitePCLRaw.bundle_e_sqlite3.2.1.10\lib\net461\SQLitePCLRaw.batteries_v2.dll + + + packages\SQLitePCLRaw.core.2.1.10\lib\netstandard2.0\SQLitePCLRaw.core.dll + + + packages\SQLitePCLRaw.provider.dynamic_cdecl.2.1.10\lib\netstandard2.0\SQLitePCLRaw.provider.dynamic_cdecl.dll + + + ..\..\..\Bosch FA\FSM5000FSI-2.0.21\Release_x64\StandardCIL.dll + + + + packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll + + + + packages\System.IO.Pipelines.9.0.0\lib\net462\System.IO.Pipelines.dll + + + packages\System.Memory.4.5.5\lib\net461\System.Memory.dll + + + + packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll + + + packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + packages\System.Text.Encodings.Web.9.0.0\lib\net462\System.Text.Encodings.Web.dll + + + packages\System.Text.Json.9.0.0\lib\net462\System.Text.Json.dll + + + packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll + + + packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll + + + + + + + + + 4.0 + + + + + + + + MSBuild:Compile + Designer + + + + MSBuild:Compile + Designer + + + App.xaml + Code + + + + + + + + MainWindow.xaml + Code + + + + + + + + Code + + + True + True + Resources.resx + + + True + Settings.settings + True + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + + + + + \ No newline at end of file diff --git a/FAtoPA.Net.sln b/FAtoPA.Net.sln new file mode 100644 index 0000000..fbfdd7a --- /dev/null +++ b/FAtoPA.Net.sln @@ -0,0 +1,28 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35514.174 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FAtoPA.Net", "FAtoPA.Net.csproj", "{C158634C-A54E-41CD-A41A-6D0AFF841BE4}" +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 + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Debug|x64.ActiveCfg = Debug|x64 + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Debug|x64.Build.0 = Debug|x64 + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Release|Any CPU.Build.0 = Release|Any CPU + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Release|x64.ActiveCfg = Release|x64 + {C158634C-A54E-41CD-A41A-6D0AFF841BE4}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/FSM.cs b/FSM.cs new file mode 100644 index 0000000..fa18635 --- /dev/null +++ b/FSM.cs @@ -0,0 +1,288 @@ +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; + 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"; + config.AdvancedFSIConfig = new AdvancedFSIConfig(); + } + + /// + /// 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(); + //Console.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)) type_dictionary.Add(type, devItemType.Description); + + } + + } + + /// + /// 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); + // notify all listeners + if (listeners != null) + foreach (var item in listeners) + item.DiscoveredSIID(SIID, nodeData); + + } + } + + } + + /// + /// 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); + + // notify all listeners + if (listeners != null) + foreach (var item in listeners) + item.NewState(SIID, prev, nd.State); + + if (prev != null) + { + Debug.WriteLine("SIID=" + SIID + " Change LogicalState from " + prev.LogicalState + " to " + nd.State.LogicalState); + } + else + { + Debug.WriteLine("New State for SIID=" + SIID + " LogicalState=" + nd.State.LogicalState); + } + } 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.Write(message); + } + + public override void WriteLine(string message) + { + if (message != null && message.Length > 0) Debug.WriteLine(message); + } + } + +} diff --git a/FSMResultInterface.cs b/FSMResultInterface.cs new file mode 100644 index 0000000..9fcee90 --- /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..35b78c3 --- /dev/null +++ b/MainWindow.xaml @@ -0,0 +1,279 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +