diff --git a/01_DCS/Hooks/Perun.lua b/01_DCS/Hooks/Perun.lua index 7dd6fb1..f1f2c2e 100644 --- a/01_DCS/Hooks/Perun.lua +++ b/01_DCS/Hooks/Perun.lua @@ -9,18 +9,18 @@ package.cpath = package.cpath..";"..lfs.currentdir().."/LuaSocket/?.dll" Perun.RefreshStatus = 15 -- (int) base refresh rate in seconds to send status update (values lower than 60 may affect performance!) Perun.RefreshMission = 60 -- (int) refresh rate in seconds to send mission information (values lower than 60 may affect performance!) -Perun.UDPTargetPort = 48620 -- (int) UDP port to send data to -Perun.UDPSourcePort = 48621 -- (int) UDP port to send data from +Perun.TCPTargetPort = 48621 -- (int) TCP port to send data to +Perun.TCPPerunHost = "localhost" -- (string) IP adress of the Perun instance or "localhost" Perun.Instance = 1 -- (int) Id number of instance (if multiple DCS instances are to run at the same PC) Perun.JsonStatusLocation = "Scripts\\Json\\" -- (string) folder relative do user's SaveGames DCS folder -> status file updated each RefreshMission -Perun.MOTD_L1 = "Witamy na serwerze Gildia.org !" -- (string) Message send to players connecting the server - Line 1 -Perun.MOTD_L2 = "Wymagamy obecnosci DCS SRS oraz TeamSpeak - szczegoly na forum" -- (string) Message send to players connecting the server - Line 2 +Perun.MOTD_L1 = "Welcome to our server!" -- (string) Message send to players connecting the server - Line 1 +Perun.MOTD_L2 = "Please use SRS radio." -- (string) Message send to players connecting the server - Line 2 -- ###################### END OF SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION ###################### -- Variable init -Perun.Version = "v0.6.0" +Perun.Version = "v0.8.0" Perun.StatusData = {} Perun.SlotsData = {} Perun.MissionData = {} @@ -33,7 +33,7 @@ Perun.lastSentMission =0 Perun.JsonStatusLocation = lfs.writedir() .. Perun.JsonStatusLocation Perun.socket = require("socket") Perun.IsServer = true --DCS.isServer( ) -- TBD looks like DCS API error, always returning True -Perun.UDPSourcePort = Perun.UDPSourcePort + Perun.Instance - 1 +Perun.TCPSourcePort = Perun.TCPTargetPort + 10 + Perun.Instance - 1 -- ########### Helper function definitions ########### function stripChars(str) @@ -153,11 +153,35 @@ Perun.SideID2Name = function(id) end -- ########### Main code ########### + Perun.AddLog = function(text) -- Adds logs to DCS.log file net.log("Perun : ".. text) end +Perun.ConnectToPerun = function () + Perun.AddLog("Connecting to TCP server") + Perun.TCP = assert(Perun.socket.tcp()) + Perun.TCP:settimeout(2000) + _, err = Perun.TCP:connect(Perun.TCPPerunHost, Perun.TCPTargetPort) + if err then + Perun.AddLog("TCP connection error : " .. err) + else + Perun.AddLog("Connected to TCP server") + end +end + +Perun.SendPacket = function (data_id,temp) + _, err = Perun.TCP:send(temp) + + if err then + Perun.AddLog("Packed drop " .. data_id .. ", error: " .. err) + Perun.ConnectToPerun() + else + Perun.AddLog("Packet send " .. data_id) + end +end + Perun.UpdateJsonStatus = function() -- Updates status json file TempData={} @@ -184,8 +208,7 @@ Perun.Send = function(data_id, data_package) temp=net.lua2json(TempData) temp=stripChars(temp) - Perun.UDP:send(temp) - Perun.AddLog("Packet send "..data_id) + Perun.SendPacket(data_id,temp) end Perun.UpdateStatusPart = function(part_id, data_package) @@ -259,6 +282,7 @@ end Perun.UpdateMission = function() -- Main function for mission information updates Perun.MissionData=DCS.getCurrentMission() + -- Perun.Send(4,Perun.MissionData) end Perun.LogChat = function(playerID,msg,all) @@ -655,11 +679,7 @@ end -- ########### Finalize and set callbacks ########### if Perun.IsServer then - Perun.UDP = assert(Perun.socket.udp()) - Perun.UDP:settimeout(0) - Perun.UDP:setsockname("*", Perun.UDPSourcePort) - Perun.UDP:setpeername("127.0.0.1",Perun.UDPTargetPort) - DCS.setUserCallbacks(Perun) - net.log("Loaded - Perun - VladMordock - " .. Perun.Version ) + net.log("Perun by VladMordock was loaded: " .. Perun.Version ) + Perun.ConnectToPerun() end diff --git a/01_DCS/Json/perun_status_data.json b/01_DCS/Json/perun_status_data.json index d3f5a12..60b0742 100644 --- a/01_DCS/Json/perun_status_data.json +++ b/01_DCS/Json/perun_status_data.json @@ -1 +1 @@ - +[] diff --git a/02_Windows_App/Perun.sln b/02_Windows_App/Perun.sln index a5af109..b79023a 100644 --- a/02_Windows_App/Perun.sln +++ b/02_Windows_App/Perun.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.28307.421 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29306.81 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Perun_v1", "Perun_v1\Perun_v1.csproj", "{5A710507-92E9-4664-9B91-918B8B82F107}" EndProject diff --git a/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs b/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs index d48beb4..3900a07 100644 --- a/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs +++ b/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs @@ -3,20 +3,22 @@ using MySql.Data.MySqlClient; using Newtonsoft.Json; using System; -internal class DatabaseController +public class DatabaseController { - public static string strMySQLConnectionString; // MySQL connection string + public string strMySQLConnectionString; // MySQL connection string + public MySqlConnection connMySQL; + public bool bStatus; - public static void SendToMySql(string strRawUDPFrame) + public void SendToMySql(string strRawUDPFrame) { // Main function to send data to mysql dynamic strUDPFrame = JsonConvert.DeserializeObject(strRawUDPFrame); // Deserialize raw data string strUDPFrameType = strUDPFrame.type; string strUDPFrameTimestamp = strUDPFrame.timestamp; string strUDPFrameInstance = strUDPFrame.instance; - string strUDPFramePayload = ""; - string strUDPFramePayload_Perun = ""; - string strSQLQueryTxt = ""; + string strUDPFramePayload; + string strUDPFramePayload_Perun; + string strSQLQueryTxt; // Some frames may come without timestamp, use database currrent timestampe then @@ -84,46 +86,58 @@ internal class DatabaseController } // Connect to mysql and execute sql - MySqlConnection connMySQL = new MySqlConnection(DatabaseController.strMySQLConnectionString); try { - Console.WriteLine("Sending data to MySQL - Begin"); - connMySQL.Open(); + connMySQL = new MySqlConnection(strMySQLConnectionString); - MySqlCommand cmdMySQL = new MySqlCommand(strSQLQueryTxt, connMySQL); - MySqlDataReader rdrMySQL = cmdMySQL.ExecuteReader(); + try + { + Console.WriteLine("Sending data to MySQL - Begin"); + connMySQL.Open(); + bStatus = true; + MySqlCommand cmdMySQL = new MySqlCommand(strSQLQueryTxt, connMySQL); + MySqlDataReader rdrMySQL = cmdMySQL.ExecuteReader(); - while (rdrMySQL.Read()) - { - Console.WriteLine(rdrMySQL[0] + " -- " + rdrMySQL[1]); + while (rdrMySQL.Read()) + { + Console.WriteLine(rdrMySQL[0] + " -- " + rdrMySQL[1]); + } + rdrMySQL.Close(); + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + strUDPFrameInstance + " > MySQL updated, package type: " + strUDPFrameType); } - rdrMySQL.Close(); - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#"+strUDPFrameInstance + " > MySQL updated, package type: " + strUDPFrameType); - } - catch (ArgumentException a_ex) - { - // General exception found - Console.WriteLine(a_ex.ToString()); - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType); - } - catch (MySqlException m_ex) - { - // MySQL exception found - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType); - switch (m_ex.Number) + catch (ArgumentException a_ex) { - case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port) - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - unable to connect"); - break; - case 0: // Access denied (Check DB name,username,password) - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - access denied"); - break; - default: - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - " + m_ex.Number); - break; + // General exception found + Console.WriteLine(a_ex.ToString()); + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType); + bStatus = false; } + catch (MySqlException m_ex) + { + // MySQL exception found + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - package type: " + strUDPFrameType); + switch (m_ex.Number) + { + case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port) + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - unable to connect"); + break; + case 0: // Access denied (Check DB name,username,password) + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - access denied"); + break; + default: + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - " + m_ex.Number); + break; + } + bStatus = false; + } + connMySQL.Close(); + Console.WriteLine("Sending data to MySQL - Done"); } - connMySQL.Close(); - Console.WriteLine("Sending data to MySQL - Done"); + catch (ArgumentException) + { + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "ERROR MySQL - wrong connection parameters"); + } + + } } diff --git a/02_Windows_App/Perun_v1/01_Classes/Globals.cs b/02_Windows_App/Perun_v1/01_Classes/Globals.cs index 2ccb6ec..0e65acb 100644 --- a/02_Windows_App/Perun_v1/01_Classes/Globals.cs +++ b/02_Windows_App/Perun_v1/01_Classes/Globals.cs @@ -1,7 +1,10 @@ -// This class gathers all global variables +// This class gathers all global variable +using MySql.Data.MySqlClient; internal class Globals { public static string strPerunVersion = "DEBUG"; // Helper for pulling version definition public static string[] arrLogHistory = new string[10]; // Log history for GUI -} \ No newline at end of file + public static string strPerunTitleText = ""; +} + diff --git a/02_Windows_App/Perun_v1/01_Classes/Program.cs b/02_Windows_App/Perun_v1/01_Classes/Program.cs index 001bb6d..59686ac 100644 --- a/02_Windows_App/Perun_v1/01_Classes/Program.cs +++ b/02_Windows_App/Perun_v1/01_Classes/Program.cs @@ -11,37 +11,21 @@ namespace Perun_v1 /// // Mutex to block multiple instances - static Mutex mutex = new Mutex(true, "{5a710507-92e9-4664-9b91-918b8b82f107}"); + //static Mutex mutex = new Mutex(true, "{5a710507-92e9-4664-9b91-918b8b82f107}"); [STAThread] static void Main() { - // Check if no other instances running - if (mutex.WaitOne(TimeSpan.Zero, true)) - { - // Only instance - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.ApplicationExit += new EventHandler(Application_ApplicationExit); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.ApplicationExit += new EventHandler(Application_ApplicationExit); - void Application_ApplicationExit(object sender, EventArgs e) - { - Properties.Settings.Default.Save(); // We will save settings on exit - } - Application.Run(new form_Main()); // Run main form - mutex.ReleaseMutex(); // Release mutex - } - else + void Application_ApplicationExit(object sender, EventArgs e) { - // Multiple instance - send our Win32 message to make the currently running instance jump to front - NativeMethods.PostMessage( - (IntPtr)NativeMethods.HWND_BROADCAST, - NativeMethods.WM_SHOWME, - IntPtr.Zero, - IntPtr.Zero); - MessageBox.Show("Only one Perun instance is allowed.", "Warning", MessageBoxButtons.OK, MessageBoxIcon.Information); + Properties.Settings.Default.Save(); // We will save settings on exit } + Application.Run(new form_Main()); // Run main form } } } diff --git a/02_Windows_App/Perun_v1/01_Classes/TCPController.cs b/02_Windows_App/Perun_v1/01_Classes/TCPController.cs new file mode 100644 index 0000000..7c682a8 --- /dev/null +++ b/02_Windows_App/Perun_v1/01_Classes/TCPController.cs @@ -0,0 +1,146 @@ +// This class handles TCP communication +using Newtonsoft.Json; +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Windows.Forms; + +public class TCPController +{ + // Main class for TCP listener + public int intListenPort; // Port to connect to + public bool bDone; // Helper to exit main loop without killing thread + public string[] arrLogHistory; // Log history for GUI + public string[] arrSendBuffer; // Mysql send buffer + public Thread thrTCPListener; // Seperate thread for TCP + public bool bStatus; // TCP connecion status + + public void Create(int par_intListenPort, ref string[] par_arrLogHistory, ref string[] par_arrSendBuffer) + { + // Create class + intListenPort = par_intListenPort; + arrLogHistory = par_arrLogHistory; + arrSendBuffer = par_arrSendBuffer; + bDone = false; + bStatus = false; + } + + public void StopListen() + { + // Finish listening + bDone = true; + bStatus = false; + + for (int i = 0; i < arrSendBuffer.Length - 1; i++) + { + arrSendBuffer[i] = null; + } + } + + public void StartListen() + { + NetworkStream ns=null; + TcpClient tcpClient=null; + + while (!bDone) + { + Console.WriteLine("TCP Listen start"); + TcpListener tcpServer = new TcpListener(IPAddress.Any, intListenPort); ; // Listener object + + try + { + // Start listening to TCP + string strReceivedData; + + // Start the main loop + tcpServer.Start(); + bStatus = true; + while (!bDone) + { + // Start listening + + Console.WriteLine("TCP: Waiting for packet"); + tcpClient = tcpServer.AcceptTcpClient(); //if a connection exists, the server will accept it + ns = tcpClient.GetStream(); //networkstream is used to send/receive messages + //ns.ReadTimeout = 100; + + while (tcpClient.Connected && !bDone) //while the client is connected, we look for incoming messages + { + StringBuilder CompleteMessage = new StringBuilder(); + + if (ns.CanRead) + { + byte[] ReadBuffer = new byte[1024]; + CompleteMessage = new StringBuilder(); + int numberOfBytesRead = 0; + + // Incoming message may be larger than the buffer size. + do + { + numberOfBytesRead = ns.Read(ReadBuffer, 0, ReadBuffer.Length); + CompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(ReadBuffer, 0, numberOfBytesRead)); + } + while (ns.DataAvailable && !bDone); + } + strReceivedData = CompleteMessage.ToString(); + Console.WriteLine("Sender: {0} Payload: {1}", null, strReceivedData); + + try + { + dynamic dynamicRawTCPFrame = JsonConvert.DeserializeObject(strReceivedData); // Deserialize received frame + string strRawTCPFrameType = dynamicRawTCPFrame.type; + + PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP packet received, type: " + strRawTCPFrameType); + + // Add to mySQL send buffer (find first empty slot) + for (int i = 0; i < arrSendBuffer.Length - 1; i++) + { + if (arrSendBuffer[i] == null) + { + arrSendBuffer[i] = strReceivedData; + break; + } + } + } + catch(Exception e) + { + Console.WriteLine(e.ToString()); + PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP ERROR incorrect JSON"); + } + } + + } + tcpServer.Stop(); + bStatus = false; + } + catch (Exception e) + { + // General exception found + if (e.HResult != -2147467259) + { + Console.WriteLine(e.ToString()); + PerunHelper.LogHistoryAdd(ref arrLogHistory, "TCP error - connection closed or port in use"); + } + + } + + if (!(ns is null)) + { + ns.Flush(); + ns.Close(); + } + if (!(tcpClient is null)) + { + tcpClient.Close(); + } + if (!(tcpServer is null)) + { + tcpServer.Stop(); + } + bStatus = false; + Console.WriteLine("TCP listen stop"); + } + } +} diff --git a/02_Windows_App/Perun_v1/01_Classes/UDPController.cs b/02_Windows_App/Perun_v1/01_Classes/UDPController.cs deleted file mode 100644 index 1dc1375..0000000 --- a/02_Windows_App/Perun_v1/01_Classes/UDPController.cs +++ /dev/null @@ -1,91 +0,0 @@ -// This class handles UDP communication -using Newtonsoft.Json; -using System; -using System.Net; -using System.Net.Sockets; -using System.Text; -using System.Threading; -using System.Windows.Forms; - -internal class UDPController -{ - // Main class for UDP listener - public static int intListenPort; // Port to listen at - public static bool boolDone; // Helper to exit main loop without killing thread - public static UdpClient udpListener; // Listener object - public static string[] arrLogHistory; // Log history for GUI - public static string[] arrSendBuffer; // Mysql send buffer - public static Thread thrUDPListener; // Seperate thread for UDP - - public static void Create(int intListenPort, ref string[] arrLogHistory, ref string[] arrSendBuffer) - { - // Create class - UDPController.intListenPort = intListenPort; - UDPController.arrLogHistory = arrLogHistory; - UDPController.arrSendBuffer = arrSendBuffer; - } - - public static void StopListen() - { - // FInish listening - UDPController.boolDone = true; - UDPController.udpListener.Close(); - UDPController.udpListener = null; - - for (int i = 0; i < arrSendBuffer.Length - 1; i++) - { - arrSendBuffer[i] = null; - } - - } - - public static void StartListen() - { - Console.WriteLine("UDP Listen start"); - try - { - // Start listening to UDP - - udpListener = new UdpClient(intListenPort); - IPEndPoint ipendpointGroupEP = new IPEndPoint(IPAddress.Loopback, intListenPort); - string strReceivedData; - byte[] arrReceiveByteArray; - - // Start the main loop - UDPController.boolDone = false; - while (!UDPController.boolDone) - { - // Start listening - Console.WriteLine("UDP: Waiting for packet"); - arrReceiveByteArray = udpListener.Receive(ref ipendpointGroupEP); - strReceivedData = Encoding.ASCII.GetString(arrReceiveByteArray, 0, arrReceiveByteArray.Length); - Console.WriteLine("Sender: {0} Payload: {1}", ipendpointGroupEP.ToString(), strReceivedData); - - // Add to log history and rotate - dynamic dynamicRawUDPFrame = JsonConvert.DeserializeObject(strReceivedData); // Deserialize received frame - string strRawUDPFrameType = dynamicRawUDPFrame.type; - PerunHelper.LogHistoryAdd(ref arrLogHistory, "UDP packet received, type: " + strRawUDPFrameType); - - // Add to mySQL send buffer (find first empty slot) - for (int i = 0; i < arrSendBuffer.Length - 1; i++) - { - if (arrSendBuffer[i] == null) - { - arrSendBuffer[i] = strReceivedData; - break; - } - } - } - udpListener.Close(); // Close port - } - catch (Exception e) - { - // General exception found - if (e.HResult != -2147467259) { - Console.WriteLine(e.ToString()); - PerunHelper.LogHistoryAdd(ref arrLogHistory, "ERROR UDP - port may be in use"); - } - } - Console.WriteLine("UDP listen stop"); - } -} \ No newline at end of file diff --git a/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs b/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs index 723b816..36951ba 100644 --- a/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs +++ b/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs @@ -61,14 +61,22 @@ this.tim_200ms = new System.Windows.Forms.Timer(this.components); this.notifyIcon1 = new System.Windows.Forms.NotifyIcon(this.components); this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.con_txt_3rd_lotatc2 = new System.Windows.Forms.MaskedTextBox(); - this.con_txt_3rd_srs2 = new System.Windows.Forms.MaskedTextBox(); - this.con_check_3rd_lotatc2 = new System.Windows.Forms.CheckBox(); - this.con_check_3rd_srs2 = new System.Windows.Forms.CheckBox(); + this.label8 = new System.Windows.Forms.Label(); + this.con_txt_dcs_instance = new System.Windows.Forms.MaskedTextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.con_txt_dcs_server_port = new System.Windows.Forms.MaskedTextBox(); + this.con_img_lotATC = new System.Windows.Forms.PictureBox(); + this.con_img_srs = new System.Windows.Forms.PictureBox(); + this.con_img_dcs = new System.Windows.Forms.PictureBox(); + this.con_img_db = new System.Windows.Forms.PictureBox(); this.con_GroupBox_1.SuspendLayout(); this.con_GroupBox_2.SuspendLayout(); this.con_GroupBox_3.SuspendLayout(); this.groupBox1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_db)).BeginInit(); this.SuspendLayout(); // // con_List_Received @@ -76,7 +84,7 @@ this.con_List_Received.Enabled = false; this.con_List_Received.FormattingEnabled = true; this.con_List_Received.Items.AddRange(new object[] { - "Welcome to Perun for DCS World!"}); + "Not connected"}); this.con_List_Received.Location = new System.Drawing.Point(6, 19); this.con_List_Received.Name = "con_List_Received"; this.con_List_Received.Size = new System.Drawing.Size(307, 147); @@ -84,34 +92,34 @@ // // con_Button_Listen_ON // - this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 517); + this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 553); this.con_Button_Listen_ON.Name = "con_Button_Listen_ON"; this.con_Button_Listen_ON.Size = new System.Drawing.Size(86, 39); this.con_Button_Listen_ON.TabIndex = 2; - this.con_Button_Listen_ON.Text = "Connect"; + this.con_Button_Listen_ON.Text = "Start"; this.con_Button_Listen_ON.UseVisualStyleBackColor = true; this.con_Button_Listen_ON.Click += new System.EventHandler(this.con_Button_Listen_ON_Click); // // con_Button_Listen_OFF // this.con_Button_Listen_OFF.Enabled = false; - this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 517); + this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 553); this.con_Button_Listen_OFF.Name = "con_Button_Listen_OFF"; this.con_Button_Listen_OFF.Size = new System.Drawing.Size(86, 39); this.con_Button_Listen_OFF.TabIndex = 3; - this.con_Button_Listen_OFF.Text = "Disconnect"; + this.con_Button_Listen_OFF.Text = "Stop"; this.con_Button_Listen_OFF.UseVisualStyleBackColor = true; this.con_Button_Listen_OFF.Click += new System.EventHandler(this.con_Button_Listen_OFF_Click); // // con_GroupBox_1 // this.con_GroupBox_1.Controls.Add(this.con_List_Received); - this.con_GroupBox_1.Location = new System.Drawing.Point(12, 335); + this.con_GroupBox_1.Location = new System.Drawing.Point(12, 369); this.con_GroupBox_1.Name = "con_GroupBox_1"; this.con_GroupBox_1.Size = new System.Drawing.Size(324, 176); this.con_GroupBox_1.TabIndex = 4; this.con_GroupBox_1.TabStop = false; - this.con_GroupBox_1.Text = "UDP log"; + this.con_GroupBox_1.Text = "Data log"; // // tim_1000ms // @@ -148,7 +156,6 @@ // // con_txt_mysql_port // - this.con_txt_mysql_port.Enabled = false; this.con_txt_mysql_port.Location = new System.Drawing.Point(106, 45); this.con_txt_mysql_port.Name = "con_txt_mysql_port"; this.con_txt_mysql_port.Size = new System.Drawing.Size(207, 20); @@ -225,12 +232,12 @@ this.con_GroupBox_3.Controls.Add(this.con_txt_3rd_srs); this.con_GroupBox_3.Controls.Add(this.con_check_3rd_lotatc); this.con_GroupBox_3.Controls.Add(this.con_check_3rd_srs); - this.con_GroupBox_3.Location = new System.Drawing.Point(12, 187); + this.con_GroupBox_3.Location = new System.Drawing.Point(12, 261); this.con_GroupBox_3.Name = "con_GroupBox_3"; this.con_GroupBox_3.Size = new System.Drawing.Size(324, 68); this.con_GroupBox_3.TabIndex = 6; this.con_GroupBox_3.TabStop = false; - this.con_GroupBox_3.Text = "Instance #1"; + this.con_GroupBox_3.Text = "3rd party"; // // con_txt_3rd_lotatc // @@ -270,7 +277,7 @@ // // con_Button_Quit // - this.con_Button_Quit.Location = new System.Drawing.Point(251, 517); + this.con_Button_Quit.Location = new System.Drawing.Point(251, 553); this.con_Button_Quit.Name = "con_Button_Quit"; this.con_Button_Quit.Size = new System.Drawing.Size(86, 39); this.con_Button_Quit.TabIndex = 7; @@ -332,63 +339,100 @@ // // groupBox1 // - this.groupBox1.Controls.Add(this.con_txt_3rd_lotatc2); - this.groupBox1.Controls.Add(this.con_txt_3rd_srs2); - this.groupBox1.Controls.Add(this.con_check_3rd_lotatc2); - this.groupBox1.Controls.Add(this.con_check_3rd_srs2); - this.groupBox1.Location = new System.Drawing.Point(12, 261); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.con_txt_dcs_instance); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.con_txt_dcs_server_port); + this.groupBox1.Location = new System.Drawing.Point(12, 187); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(324, 68); this.groupBox1.TabIndex = 7; this.groupBox1.TabStop = false; - this.groupBox1.Text = "Instance #2"; + this.groupBox1.Text = "DCS Connection"; // - // con_txt_3rd_lotatc2 + // label8 // - this.con_txt_3rd_lotatc2.Location = new System.Drawing.Point(123, 39); - this.con_txt_3rd_lotatc2.Name = "con_txt_3rd_lotatc2"; - this.con_txt_3rd_lotatc2.Size = new System.Drawing.Size(190, 20); - this.con_txt_3rd_lotatc2.TabIndex = 4; - this.con_txt_3rd_lotatc2.MouseClick += new System.Windows.Forms.MouseEventHandler(this.con_txt_3rd_lotatc2_Click); + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(41, 45); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(62, 13); + this.label8.TabIndex = 12; + this.label8.Text = "Instance ID"; // - // con_txt_3rd_srs2 + // con_txt_dcs_instance // - this.con_txt_3rd_srs2.Location = new System.Drawing.Point(123, 16); - this.con_txt_3rd_srs2.Name = "con_txt_3rd_srs2"; - this.con_txt_3rd_srs2.Size = new System.Drawing.Size(190, 20); - this.con_txt_3rd_srs2.TabIndex = 3; - this.con_txt_3rd_srs2.MouseClick += new System.Windows.Forms.MouseEventHandler(this.con_txt_3rd_srs2_Click); + this.con_txt_dcs_instance.Location = new System.Drawing.Point(106, 42); + this.con_txt_dcs_instance.Name = "con_txt_dcs_instance"; + this.con_txt_dcs_instance.Size = new System.Drawing.Size(207, 20); + this.con_txt_dcs_instance.TabIndex = 11; // - // con_check_3rd_lotatc2 + // label7 // - this.con_check_3rd_lotatc2.AutoSize = true; - this.con_check_3rd_lotatc2.Location = new System.Drawing.Point(6, 42); - this.con_check_3rd_lotatc2.Name = "con_check_3rd_lotatc2"; - this.con_check_3rd_lotatc2.Size = new System.Drawing.Size(100, 17); - this.con_check_3rd_lotatc2.TabIndex = 1; - this.con_check_3rd_lotatc2.Text = "LotATC json file"; - this.con_check_3rd_lotatc2.UseVisualStyleBackColor = true; + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(41, 19); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(59, 13); + this.label7.TabIndex = 10; + this.label7.Text = "Server port"; // - // con_check_3rd_srs2 + // con_txt_dcs_server_port // - this.con_check_3rd_srs2.AutoSize = true; - this.con_check_3rd_srs2.Location = new System.Drawing.Point(6, 19); - this.con_check_3rd_srs2.Name = "con_check_3rd_srs2"; - this.con_check_3rd_srs2.Size = new System.Drawing.Size(111, 17); - this.con_check_3rd_srs2.TabIndex = 0; - this.con_check_3rd_srs2.Text = "DCS SRS json file"; - this.con_check_3rd_srs2.UseVisualStyleBackColor = true; + this.con_txt_dcs_server_port.Location = new System.Drawing.Point(106, 16); + this.con_txt_dcs_server_port.Name = "con_txt_dcs_server_port"; + this.con_txt_dcs_server_port.Size = new System.Drawing.Size(207, 20); + this.con_txt_dcs_server_port.TabIndex = 3; + // + // con_img_lotATC + // + this.con_img_lotATC.Location = new System.Drawing.Point(307, 335); + this.con_img_lotATC.Name = "con_img_lotATC"; + this.con_img_lotATC.Size = new System.Drawing.Size(29, 28); + this.con_img_lotATC.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.con_img_lotATC.TabIndex = 13; + this.con_img_lotATC.TabStop = false; + // + // con_img_srs + // + this.con_img_srs.Location = new System.Drawing.Point(272, 335); + this.con_img_srs.Name = "con_img_srs"; + this.con_img_srs.Size = new System.Drawing.Size(29, 28); + this.con_img_srs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.con_img_srs.TabIndex = 12; + this.con_img_srs.TabStop = false; + // + // con_img_dcs + // + this.con_img_dcs.Location = new System.Drawing.Point(237, 335); + this.con_img_dcs.Name = "con_img_dcs"; + this.con_img_dcs.Size = new System.Drawing.Size(29, 28); + this.con_img_dcs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.con_img_dcs.TabIndex = 11; + this.con_img_dcs.TabStop = false; + // + // con_img_db + // + this.con_img_db.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; + this.con_img_db.Location = new System.Drawing.Point(202, 335); + this.con_img_db.Name = "con_img_db"; + this.con_img_db.Size = new System.Drawing.Size(29, 28); + this.con_img_db.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.con_img_db.TabIndex = 10; + this.con_img_db.TabStop = false; // // form_Main // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(349, 558); + this.ClientSize = new System.Drawing.Size(349, 604); + this.Controls.Add(this.con_img_lotATC); + this.Controls.Add(this.con_img_srs); + this.Controls.Add(this.con_img_dcs); + this.Controls.Add(this.con_img_db); this.Controls.Add(this.groupBox1); + this.Controls.Add(this.con_GroupBox_3); this.Controls.Add(this.label5); this.Controls.Add(this.con_lab_github); this.Controls.Add(this.con_Button_Quit); - this.Controls.Add(this.con_GroupBox_3); this.Controls.Add(this.con_GroupBox_2); this.Controls.Add(this.con_GroupBox_1); this.Controls.Add(this.con_Button_Listen_OFF); @@ -409,6 +453,10 @@ this.con_GroupBox_3.PerformLayout(); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.con_img_db)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); @@ -447,10 +495,14 @@ private System.Windows.Forms.Timer tim_200ms; private System.Windows.Forms.NotifyIcon notifyIcon1; private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.MaskedTextBox con_txt_3rd_lotatc2; - private System.Windows.Forms.MaskedTextBox con_txt_3rd_srs2; - private System.Windows.Forms.CheckBox con_check_3rd_lotatc2; - private System.Windows.Forms.CheckBox con_check_3rd_srs2; + private System.Windows.Forms.MaskedTextBox con_txt_dcs_server_port; + private System.Windows.Forms.Label label7; + private System.Windows.Forms.Label label8; + private System.Windows.Forms.MaskedTextBox con_txt_dcs_instance; + private System.Windows.Forms.PictureBox con_img_db; + private System.Windows.Forms.PictureBox con_img_dcs; + private System.Windows.Forms.PictureBox con_img_srs; + private System.Windows.Forms.PictureBox con_img_lotATC; } } diff --git a/02_Windows_App/Perun_v1/02_Forms/form_Main.cs b/02_Windows_App/Perun_v1/02_Forms/form_Main.cs index cd3e7f9..8bca802 100644 --- a/02_Windows_App/Perun_v1/02_Forms/form_Main.cs +++ b/02_Windows_App/Perun_v1/02_Forms/form_Main.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Drawing; using System.Threading; using System.Windows.Forms; using Newtonsoft.Json; @@ -9,17 +10,62 @@ namespace Perun_v1 public partial class form_Main : Form { // Variable definitions - public string[] arrSendBuffer = new string[100]; // Mysql send buffer - public bool boolLetMeOut = false; // Helper to handle system tray + public string[] arrSendBuffer = new string[65534]; // MySQL send buffer + public bool bLetMeOut = false; // Helper to handle system tray + + public DatabaseController dcConnection = new DatabaseController(); // MySQL controller + public TCPController tcpcServer=new TCPController(); // TCP controller + + public bool bSRSStatus; // Use empty/default SRS status + public bool bLotATCStatus; // Use empty/default LotATC status // ################################ Main ################################ private void form_Main_Load(object sender, EventArgs e) { // Form loaded - fill controls with default values - Globals.arrLogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun started"; - form_Main_LoadSettings(); // Load settings - this.Text = PerunHelper.GetAppVersion(this.Text + " - "); // Display build version in title bar + + Globals.strPerunTitleText = PerunHelper.GetAppVersion(this.Text + " - "); // Display build version in title bar + this.Text = Globals.strPerunTitleText; + + form_Main_LoadSettings(); // Load settings + + // Use command line parameters + string[] args = Environment.GetCommandLineArgs(); + if (args.Length > 1) + { + // server port + if (args[1] != null) + { + con_txt_dcs_server_port.Text = args[1]; + } + } + if (args.Length > 2) + { + // instance id + if (args[2] != null) + { + con_txt_dcs_instance.Text = args[2]; + } + } + if (args.Length > 3) + { + // srs + if (args[3] != null) + { + con_txt_3rd_srs.Text = args[3]; + con_check_3rd_srs.Checked = true; + } + } + if (args.Length > 4) + { + // lotatc + if (args[4] != null) + { + con_txt_3rd_lotatc.Text = args[4]; + con_check_3rd_lotatc.Checked = true; + } + } } public form_Main() @@ -41,10 +87,9 @@ namespace Perun_v1 con_txt_3rd_srs.Text = Properties.Settings.Default.OTHER_SRS_FILE; con_check_3rd_lotatc.Checked = Properties.Settings.Default.OTHER_LOTATC_USE; con_check_3rd_srs.Checked = Properties.Settings.Default.OTHER_SRS_USE; - con_txt_3rd_lotatc2.Text = Properties.Settings.Default.OTHER_LOTATC_FILE2; - con_txt_3rd_srs2.Text = Properties.Settings.Default.OTHER_SRS_FILE2; - con_check_3rd_lotatc2.Checked = Properties.Settings.Default.OTHER_LOTATC_USE2; - con_check_3rd_srs2.Checked = Properties.Settings.Default.OTHER_SRS_USE2; + con_txt_dcs_server_port.Text = Properties.Settings.Default.DCS_Server_Port.ToString(); + con_txt_dcs_instance.Text = Properties.Settings.Default.DCS_Instance.ToString(); + } private void form_Main_SaveSettings() @@ -61,10 +106,8 @@ namespace Perun_v1 Properties.Settings.Default.OTHER_SRS_FILE = con_txt_3rd_srs.Text; Properties.Settings.Default.OTHER_LOTATC_USE = con_check_3rd_lotatc.Checked; Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked; - Properties.Settings.Default.OTHER_LOTATC_FILE2 = con_txt_3rd_lotatc2.Text; - Properties.Settings.Default.OTHER_SRS_FILE2 = con_txt_3rd_srs2.Text; - Properties.Settings.Default.OTHER_LOTATC_USE2 = con_check_3rd_lotatc2.Checked; - Properties.Settings.Default.OTHER_SRS_USE2 = con_check_3rd_srs2.Checked; + Properties.Settings.Default.DCS_Server_Port = Int32.Parse(con_txt_dcs_server_port.Text); + Properties.Settings.Default.DCS_Instance = Int32.Parse(con_txt_dcs_instance.Text); Properties.Settings.Default.Save(); } @@ -83,10 +126,8 @@ namespace Perun_v1 con_txt_3rd_srs.Enabled = false; con_check_3rd_lotatc.Enabled = false; con_check_3rd_srs.Enabled = false; - con_txt_3rd_lotatc2.Enabled = false; - con_txt_3rd_srs2.Enabled = false; - con_check_3rd_lotatc2.Enabled = false; - con_check_3rd_srs2.Enabled = false; + con_txt_dcs_server_port.Enabled = false; + con_txt_dcs_instance.Enabled = false; } private void form_Main_EnableControls() @@ -94,61 +135,90 @@ namespace Perun_v1 // Enables controls con_Button_Listen_ON.Enabled = true; con_Button_Listen_OFF.Enabled = false; - con_txt_mysql_database.Enabled = true; con_txt_mysql_username.Enabled = true; con_txt_mysql_password.Enabled = true; - //con_txt_mysql_port.Enabled = true; // TBD - protect against writting text in the port field + con_txt_mysql_port.Enabled = true; con_txt_mysql_server.Enabled = true; con_txt_3rd_lotatc.Enabled = true; con_txt_3rd_srs.Enabled = true; con_check_3rd_lotatc.Enabled = true; con_check_3rd_srs.Enabled = true; - con_txt_3rd_lotatc2.Enabled = true; - con_txt_3rd_srs2.Enabled = true; - con_check_3rd_lotatc2.Enabled = true; - con_check_3rd_srs2.Enabled = true; + con_txt_dcs_server_port.Enabled = true; + con_txt_dcs_instance.Enabled = true; } // ################################ User input ################################ private void con_Button_Listen_ON_Click(object sender, EventArgs e) { // Start listening - UDPController.Create(48620, ref Globals.arrLogHistory, ref arrSendBuffer); - UDPController.thrUDPListener = new Thread(UDPController.StartListen); - UDPController.thrUDPListener.Start(); - UDPController.thrUDPListener.Name = "UDPThread"; + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Opening connections"); + tcpcServer.Create(Int32.Parse(con_txt_dcs_server_port.Text), ref Globals.arrLogHistory, ref arrSendBuffer); + tcpcServer.thrTCPListener = new Thread(tcpcServer.StartListen); + tcpcServer.thrTCPListener.Start(); + tcpcServer.thrTCPListener.Name = "TCPThread"; - form_Main_DisableControls(); // Disable controlls - form_Main_SaveSettings(); // Save settings + form_Main_DisableControls(); // Disable controlls + form_Main_SaveSettings(); // Save settings // Prepare connection string - DatabaseController.strMySQLConnectionString = "server=" + con_txt_mysql_server.Text + ";user=" + con_txt_mysql_username.Text + ";database=" + con_txt_mysql_database.Text + ";port=" + con_txt_mysql_port.Text + ";password=" + con_txt_mysql_password.Text; + dcConnection.strMySQLConnectionString = "server=" + con_txt_mysql_server.Text + ";user=" + con_txt_mysql_username.Text + ";database=" + con_txt_mysql_database.Text + ";port=" + con_txt_mysql_port.Text + ";password=" + con_txt_mysql_password.Text; // Start timmers tim_200ms.Enabled = true; tim_1000ms.Enabled = true; tim_10000ms.Enabled = true; + + // Send initial data + tim_10000ms_Tick(null, null); + + // Set title bar + this.Text = "[#"+ con_txt_dcs_instance.Text + "] " + Globals.strPerunTitleText; } private void con_Button_Listen_OFF_Click(object sender, EventArgs e) { // Stop listening + + // Display information + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Closing connections"); + con_Button_Listen_OFF.Enabled = false; + timer1_Tick(null, null); + this.Refresh(); + Application.DoEvents(); + + try { - UDPController.StopListen(); + tcpcServer.StopListen(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } + while (tcpcServer.thrTCPListener.IsAlive) + { + Thread.Sleep(100); //ms + } form_Main_EnableControls(); // Enable controls + con_img_db.Image = null; + con_img_dcs.Image = null; + con_img_lotATC.Image = null; + con_img_srs.Image = null; + // Stop timmers tim_1000ms.Enabled = false; tim_10000ms.Enabled = false; tim_200ms.Enabled = false; + + // Display information about closed connections + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "Connections closed"); + timer1_Tick(null, null); + + // Set title bar + this.Text = Globals.strPerunTitleText; } private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) @@ -188,36 +258,6 @@ namespace Perun_v1 } } - private void con_txt_3rd_srs2_Click(object sender, MouseEventArgs e) - { - // Chose SRS Json file - if (openFileDialog_SRS.ShowDialog() == DialogResult.OK) - { - con_txt_3rd_srs2.Text = openFileDialog_SRS.FileName; - con_check_3rd_srs2.Checked = true; - } - else - { - con_txt_3rd_srs2.Text = ""; - con_check_3rd_srs2.Checked = false; - } - } - - private void con_txt_3rd_lotatc2_Click(object sender, MouseEventArgs e) - { - // Chose LotATC Json file - if (openFileDialog_LotATC.ShowDialog() == DialogResult.OK) - { - con_txt_3rd_lotatc2.Text = openFileDialog_LotATC.FileName; - con_check_3rd_lotatc2.Checked = true; - } - else - { - con_txt_3rd_lotatc2.Text = ""; - con_check_3rd_lotatc2.Checked = false; - } - } - // ################################ Form state ################################ private void con_Button_Quit_Click(object sender, EventArgs e) { @@ -227,7 +267,7 @@ namespace Perun_v1 { form_Main_SaveSettings(); - boolLetMeOut = true; // Save settings on exit + bLetMeOut = true; // Save settings on exit this.Close(); // Allow to exit application } else if (dialogResult == DialogResult.No) @@ -277,7 +317,7 @@ namespace Perun_v1 private void form_Main_FormClosing(object sender, FormClosingEventArgs e) { // Minimize to try on clicking "X" - if (e.CloseReason == CloseReason.UserClosing && !boolLetMeOut) + if (e.CloseReason == CloseReason.UserClosing && !bLetMeOut) { e.Cancel = true; form_Main_SendToTray(); // Send app to system tray @@ -312,10 +352,45 @@ namespace Perun_v1 { if (arrSendBuffer[i] != null) { - DatabaseController.SendToMySql(arrSendBuffer[i]); + dcConnection.SendToMySql(arrSendBuffer[i]); arrSendBuffer[i] = null; } } + + // Update status icons at main form + if (dcConnection.bStatus) + { + con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_db"); + } else + { + con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error"); + } + if (tcpcServer.bStatus) + { + con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_game"); + } + else + { + con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error"); + } + if (bSRSStatus) + { + con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_srs"); + } + else + { + con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error"); + } + if (bLotATCStatus) + { + con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_lotatc"); + } + else + { + con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("ico_error"); + } + + } private void tim_10000ms_Tick(object sender, EventArgs e) @@ -323,15 +398,11 @@ namespace Perun_v1 // Main timer to send JSON files to MySQL string strSRSJson = ""; string strLotATCJson = ""; - string strSRSJson2 = ""; - string strLotATCJson2 = ""; bool boolSRSdefault = true; bool boolLotATCdefault = true; - bool boolSRSdefault2 = true; - bool boolLotATCdefault2 = true; - // Handle SRS - TBD clean code for multiinstance + // Handle SRS if (con_check_3rd_srs.Checked) { try @@ -373,94 +444,31 @@ namespace Perun_v1 if (raw_lotatc.Count > 0) { strSRSJson = JsonConvert.SerializeObject(raw_lotatc); - strSRSJson = "{'type':'100','instance':'1','payload':'" + strSRSJson + "'}"; + strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + strSRSJson + "'}"; } else { - strSRSJson = "{'type':'100','instance':'1','payload':{'ignore':'false'}}"; // No SRS clients connected + strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'false'}}"; // No SRS clients connected } boolSRSdefault = false; - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#1 > SRS data loaded"); - + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data loaded"); + bSRSStatus = true; } catch { - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#1 > SRS data ERROR"); + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > SRS data ERROR"); + bSRSStatus = false; } } if (boolSRSdefault) { - strSRSJson = "{'type':'100','instance':'1','payload':{'ignore':'true'}}"; + strSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; } - DatabaseController.SendToMySql(strSRSJson); + dcConnection.SendToMySql(strSRSJson); - if (con_check_3rd_srs2.Checked) - { - try - { - strSRSJson2 = System.IO.File.ReadAllText(con_txt_3rd_srs2.Text); - dynamic raw_lotatc = JsonConvert.DeserializeObject(strSRSJson2); - - for (int i = 0; i < raw_lotatc.Count; i++) - { - - if (raw_lotatc[i].RadioInfo != null) - { - - int temp = raw_lotatc[i].RadioInfo.radios.Count - 1; - for (int j = temp; j >= 0; j--) - { - raw_lotatc[i].RadioInfo.radios[j].enc.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].encKey.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].encMode.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].freqMax.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].freqMin.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].modulation.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].freqMode.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].volMode.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].expansion.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].channel.Parent.Remove(); - raw_lotatc[i].RadioInfo.radios[j].simul.Parent.Remove(); - - if (raw_lotatc[i].RadioInfo.radios[j].name == "No Radio") - { - raw_lotatc[i].RadioInfo.radios[j].Remove(); - } - } - raw_lotatc[i].ClientChannelId.Parent.Remove(); - raw_lotatc[i].RadioInfo.simultaneousTransmission.Parent.Remove(); - } - } - - if (raw_lotatc.Count > 0) - { - strSRSJson2 = JsonConvert.SerializeObject(raw_lotatc); - strSRSJson2 = "{'type':'100','instance':'2','payload':'" + strSRSJson2 + "'}"; - } - else - { - strSRSJson2 = "{'type':'100','instance':'2','payload':{'ignore':'false'}}"; // No SRS clients connected - } - boolSRSdefault2 = false; - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#2 > SRS data loaded"); - - } - catch - { - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#2 > SRS data ERROR"); - } - - - } - if (boolSRSdefault2) - { - strSRSJson2 = "{'type':'100','instance':'2','payload':{'ignore':'true'}}"; - } - DatabaseController.SendToMySql(strSRSJson2); - - // Handle LotATC - TBD clean code for multiinstance + // Handle LotATC if (con_check_3rd_lotatc.Checked) { try @@ -468,46 +476,24 @@ namespace Perun_v1 strLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text); dynamic raw_srs = JsonConvert.DeserializeObject(strLotATCJson); - strLotATCJson = "{'type':'101','instance':'1','payload':'" + strLotATCJson + "'}"; + strLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + strLotATCJson + "'}"; boolLotATCdefault = false; - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#1 > LotATC data loaded"); + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > LotATC data loaded"); + bLotATCStatus = true; } catch { - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#1 > LotATC data ERROR"); + PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#" + Int32.Parse(con_txt_dcs_instance.Text) + " > LotATC data ERROR"); + bLotATCStatus = false; } } if (boolLotATCdefault) { - strLotATCJson = "{'type':'101','instance':'1','payload':{'ignore':'true'}}"; // No LotATC controller connected + strLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; // No LotATC controller connected } - DatabaseController.SendToMySql(strLotATCJson); - - if (con_check_3rd_lotatc2.Checked) - { - try - { - strLotATCJson2 = System.IO.File.ReadAllText(con_txt_3rd_lotatc2.Text); - dynamic raw_srs = JsonConvert.DeserializeObject(strLotATCJson2); - - strLotATCJson2 = "{'type':'101','instance':'2','payload':'" + strLotATCJson2 + "'}"; - boolLotATCdefault2 = false; - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#2 > LotATC data loaded"); - } - catch - { - PerunHelper.LogHistoryAdd(ref Globals.arrLogHistory, "#2 > LotATC data ERROR"); - } - - - } - if (boolLotATCdefault2) - { - strLotATCJson2 = "{'type':'101','instance':'2','payload':{'ignore':'true'}}"; // No LotATC controller connected - } - DatabaseController.SendToMySql(strLotATCJson2); + dcConnection.SendToMySql(strLotATCJson); } } } diff --git a/02_Windows_App/Perun_v1/Perun_v1.csproj b/02_Windows_App/Perun_v1/Perun_v1.csproj index c42be6f..69b9a78 100644 --- a/02_Windows_App/Perun_v1/Perun_v1.csproj +++ b/02_Windows_App/Perun_v1/Perun_v1.csproj @@ -8,11 +8,12 @@ WinExe Perun_v1 Perun - v4.6.1 + v4.8 512 true true true + ftp://s18.mydevil.net/perun/ true Web @@ -32,8 +33,8 @@ Perun true Perun.htm - 7 - 0.7.0.%2a + 0 + 0.8.0.%2a false true true @@ -74,7 +75,7 @@ true - true + false false @@ -87,14 +88,20 @@ Properties\app.manifest - - ..\packages\Google.Protobuf.3.5.1\lib\net45\Google.Protobuf.dll + + ..\packages\BouncyCastle.1.8.3.1\lib\BouncyCastle.Crypto.dll - - ..\packages\MySql.Data.8.0.15\lib\net452\MySql.Data.dll + + ..\packages\Google.Protobuf.3.6.1\lib\net45\Google.Protobuf.dll + + + ..\packages\MySql.Data.8.0.17\lib\net452\MySql.Data.dll - ..\packages\Newtonsoft.Json.12.0.1\lib\net45\Newtonsoft.Json.dll + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll + + + ..\packages\SSH.NET.2016.1.0\lib\net40\Renci.SshNet.dll @@ -116,7 +123,7 @@ - + @@ -145,6 +152,7 @@ + SettingsSingleFileGenerator @@ -162,7 +170,7 @@ False - Microsoft .NET Framework 4.6.1 %28x86 i x64%29 + Microsoft .NET Framework 4.6.1 %28x86 and x64%29 true @@ -173,6 +181,12 @@ + + + + + + diff --git a/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs b/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs index 315e778..ef8e214 100644 --- a/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs +++ b/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ using System.Runtime.InteropServices; // Możesz określić wszystkie wartości lub użyć domyślnych numerów kompilacji i poprawki // przy użyciu symbolu „*”, tak jak pokazano poniżej: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.7.0.0")] -[assembly: AssemblyFileVersion("0.7.0.0")] +[assembly: AssemblyVersion("0.8.0.0")] +[assembly: AssemblyFileVersion("0.8.0.0")] [assembly: NeutralResourcesLanguage("en")] diff --git a/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs b/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs index 9aee274..5736650 100644 --- a/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs +++ b/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Ten kod został wygenerowany przez narzędzie. -// Wersja wykonawcza:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli -// kod zostanie ponownie wygenerowany. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -13,13 +13,13 @@ namespace Perun_v1.Properties { /// - /// Klasa zasobu wymagająca zdefiniowania typu do wyszukiwania zlokalizowanych ciągów itd. + /// A strongly-typed resource class, for looking up localized strings, etc. /// - // Ta klasa została automatycznie wygenerowana za pomocą klasy StronglyTypedResourceBuilder - // przez narzędzie, takie jak ResGen lub Visual Studio. - // Aby dodać lub usunąć składową, edytuj plik ResX, a następnie ponownie uruchom narzędzie ResGen - // z opcją /str lub ponownie utwórz projekt VS. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")] + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { @@ -33,7 +33,7 @@ namespace Perun_v1.Properties { } /// - /// Zwraca buforowane wystąpienie ResourceManager używane przez tę klasę. + /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { @@ -47,8 +47,8 @@ namespace Perun_v1.Properties { } /// - /// Przesłania właściwość CurrentUICulture bieżącego wątku dla wszystkich - /// przypadków przeszukiwania zasobów za pomocą tej klasy zasobów wymagającej zdefiniowania typu. + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { @@ -59,5 +59,55 @@ namespace Perun_v1.Properties { resourceCulture = value; } } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_db { + get { + object obj = ResourceManager.GetObject("ico_db", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_error { + get { + object obj = ResourceManager.GetObject("ico_error", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_game { + get { + object obj = ResourceManager.GetObject("ico_game", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_lotatc { + get { + object obj = ResourceManager.GetObject("ico_lotatc", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ico_srs { + get { + object obj = ResourceManager.GetObject("ico_srs", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } } } diff --git a/02_Windows_App/Perun_v1/Properties/Resources.resx b/02_Windows_App/Perun_v1/Properties/Resources.resx index 1af7de1..3bef010 100644 --- a/02_Windows_App/Perun_v1/Properties/Resources.resx +++ b/02_Windows_App/Perun_v1/Properties/Resources.resx @@ -117,4 +117,20 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + ..\Resources\ico_db.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_error.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_game.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_lotatc.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + + ..\Resources\ico_srs.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + \ No newline at end of file diff --git a/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs b/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs index 0e363a5..778c811 100644 --- a/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs +++ b/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// Ten kod został wygenerowany przez narzędzie. -// Wersja wykonawcza:4.0.30319.42000 +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 // -// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli -// kod zostanie ponownie wygenerowany. +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace Perun_v1.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); @@ -133,49 +133,25 @@ namespace Perun_v1.Properties { [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string OTHER_LOTATC_FILE2 { + [global::System.Configuration.DefaultSettingValueAttribute("48620")] + public int DCS_Server_Port { get { - return ((string)(this["OTHER_LOTATC_FILE2"])); + return ((int)(this["DCS_Server_Port"])); } set { - this["OTHER_LOTATC_FILE2"] = value; + this["DCS_Server_Port"] = value; } } [global::System.Configuration.UserScopedSettingAttribute()] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("")] - public string OTHER_SRS_FILE2 { + [global::System.Configuration.DefaultSettingValueAttribute("1")] + public int DCS_Instance { get { - return ((string)(this["OTHER_SRS_FILE2"])); + return ((int)(this["DCS_Instance"])); } set { - this["OTHER_SRS_FILE2"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool OTHER_LOTATC_USE2 { - get { - return ((bool)(this["OTHER_LOTATC_USE2"])); - } - set { - this["OTHER_LOTATC_USE2"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("False")] - public bool OTHER_SRS_USE2 { - get { - return ((bool)(this["OTHER_SRS_USE2"])); - } - set { - this["OTHER_SRS_USE2"] = value; + this["DCS_Instance"] = value; } } } diff --git a/02_Windows_App/Perun_v1/Properties/Settings.settings b/02_Windows_App/Perun_v1/Properties/Settings.settings index 137835e..37e5157 100644 --- a/02_Windows_App/Perun_v1/Properties/Settings.settings +++ b/02_Windows_App/Perun_v1/Properties/Settings.settings @@ -29,17 +29,11 @@ 3306 - - + + 48620 - - - - - False - - - False + + 1 \ No newline at end of file diff --git a/02_Windows_App/Perun_v1/Resources/ico_db.png b/02_Windows_App/Perun_v1/Resources/ico_db.png new file mode 100644 index 0000000..fb78464 Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/ico_db.png differ diff --git a/02_Windows_App/Perun_v1/Resources/ico_error.png b/02_Windows_App/Perun_v1/Resources/ico_error.png new file mode 100644 index 0000000..cd9246a Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/ico_error.png differ diff --git a/02_Windows_App/Perun_v1/Resources/ico_game.png b/02_Windows_App/Perun_v1/Resources/ico_game.png new file mode 100644 index 0000000..d906fde Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/ico_game.png differ diff --git a/02_Windows_App/Perun_v1/Resources/ico_lotatc.png b/02_Windows_App/Perun_v1/Resources/ico_lotatc.png new file mode 100644 index 0000000..7826b4c Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/ico_lotatc.png differ diff --git a/02_Windows_App/Perun_v1/Resources/ico_srs.png b/02_Windows_App/Perun_v1/Resources/ico_srs.png new file mode 100644 index 0000000..4b2d5fa Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/ico_srs.png differ diff --git a/02_Windows_App/Perun_v1/Resources/img_db.png b/02_Windows_App/Perun_v1/Resources/img_db.png new file mode 100644 index 0000000..3e9d6ed Binary files /dev/null and b/02_Windows_App/Perun_v1/Resources/img_db.png differ diff --git a/02_Windows_App/Perun_v1/app.config b/02_Windows_App/Perun_v1/app.config index 72175de..02494be 100644 --- a/02_Windows_App/Perun_v1/app.config +++ b/02_Windows_App/Perun_v1/app.config @@ -1,8 +1,8 @@ - + - -
+ +
@@ -34,18 +34,12 @@ 3306 - - + + 48620 - - - - - False - - - False + + 1 - \ No newline at end of file + diff --git a/02_Windows_App/Perun_v1/packages.config b/02_Windows_App/Perun_v1/packages.config new file mode 100644 index 0000000..fa00d4d --- /dev/null +++ b/02_Windows_App/Perun_v1/packages.config @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/README.md b/README.md index 6880f5f..71dd2e3 100644 --- a/README.md +++ b/README.md @@ -5,44 +5,71 @@ # Perun for DCS World -This toolset extracts data from DCS World server and sends information to the local Json file and UDP port for further processing. +Included lua script extracts data from DCS World multiplayer server and sends information to TCP port and JSON file for further processing. -Provided windows app puts received UDP packets to MySQL database. Additionaly Perun windows application can be used to merge LotATC and DCS SRS data in one database making Perun for DCS World wannabe ultimate integration tool for the server admins. +Provided windows app puts received TCP packets to MySQL database; additionaly Perun windows application can be used to merge LotATC and DCS SRS data in one database making Perun for DCS World wannabe ultimate integration tool for the server admins. -However, this software is intended to be used by experienced users - the output is Json data and MySQL; you will need to process/display it yourself. +However, this software is intended to be used by experienced users - the output is MySQL data and/or JSON file; you will need to process/display it yourself. -![Perun in action](https://i.imgur.com/ougQMPq.png) +![Perun in action](https://i.imgur.com/vHw8Xu5.png) ![Data flow](https://i.imgur.com/JbNu77l.png) -### Prerequisites +## Prerequisites Core: * For JSON Export: * DCS World stable or DCS World beta * **(Optional)** For MySQL Export: - * MySQL server with read/write access (tested with v5.7.21) - * .NET Framework 4.8 + * MySQL database with read/write access (tested with v5.7.21) + * .NET Framework 4.8.0 3rd party applications support: * for [DCS SRS](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) integration location of the clients-list.json file will be required (by default: SRS Server folder), "Auto Export List" option has to be enabled - see [SRS documentation](https://github.com/ciribob/DCS-SimpleRadioStandalone/wiki) * for [LotATC](https://www.lotatc.com/) you will need location of stats.json file and proper LotATC configuration with JSON data export enabled - see [LotATC documentation](https://www.lotatc.com/documentation/server_configuration.html) -### Installing +## Installing -* Download latest [release](https://github.com/szporwolik/perun/releases), **optionaly** together with windows binary file for MySQL export - [DOWNLOAD](http://share.porwolik.com/ftp/perun/Perun.htm) +* Download latest [release](https://github.com/szporwolik/perun/releases) * Copy contents of [01_DCS](https://github.com/szporwolik/perun/tree/master/01_DCS) to your \Scripts folder (located inside DCS folder in your Saved Games) -* **optionaly** Create MySQL server using SQL script located in [03_MySQL](https://github.com/szporwolik/perun/tree/master/03_MySQL) -* **optionaly** Run the Win32 application - * set MySQL connection data - * point LotATC json file location - * point DCS SRS json file location - * click connect and leave the app running in the background +* **optionaly** create MySQL database using SQL script located in [03_MySQL](https://github.com/szporwolik/perun/tree/master/03_MySQL); note that you need just a one database per DCS server machine - multiple instances pushing data to the one database are supported + +## Running * Start DCS World and host multiplayer session * by default the JSON is written into Scripts\Json folder located in your Saved Games DCS folder tree - * by default the UDP port 48620 is in use as target port -* Data shall be filling your MySQL database + * by default the TCP port 48620 is in use as target port +* **optionaly** run the Win32 application + * set MySQL connection data + * **optionaly** point LotATC json file location + * **optionaly** point DCS SRS json file location + * click connect and leave the app running in the background + * **data shall now be filling your MySQL database** -## Data packets +### Windows APP - command line arguments (for expert users) +Windows app supports command line arguments, what may be handy in case of multiple instance of DCS servers running at the same machine. + +The following arguments are accepted (keep the order!): +* server port (shall be the same as in the lua file!) +* instance ID (shall be the same as in the lua file!) +* path to SRS client-list.json +* path to LotATC stats.json + +Example for windows shortcut: +``` +C:\Perun_v1\Perun.exe 48621 1 "G:\DCS SRS\clients-list.json" "C:\Users\DCS\Saved Games\DCS\Mods\tech\LotAtc\stats.json" +``` + +# API documentation (for expert users) +## MySQL database structure +* table: pe_DataMissionHashes - holds mission hashes, unique hashes created per each mission start at server +* table: pe_DataPlayers - holds players UCIDs together with last login information +* table: pe_DataRaw - holds raw data received from perun windows app, containing debug/version information together with DCS SRS and LotATC data +* table: pe_DataTypes - names of all model depende class names detected in DCS +* table: pe_LogChat - holds chat history +* table: pe_LogEvent - holds event history +* table: pe_LogLogins - holds login to server event history +* table: pe_LogStats - holds static information + +## Data packets - send from lua to TCP port * ```ID: 1```, contains version/diagnostic information * ```ID: 2```, contains status data in the following sections * mission - minimal information about mission @@ -50,19 +77,23 @@ Core: * ```ID: 3```, available slots list and coalitions * coalitions - available coalitions * slots - available slots -* ```ID: 4```, stores mission data **WIP: not yet implemented** +* ```ID: 4```, stores mission data * ```ID: 50```, chat event * ```ID: 51```, game event -* ```ID: 52```, player stats **WIP: not yet implemented** +* ```ID: 52```, player stats * ```ID: 53```, player login to DCS server * ```ID: 100```, DCS SRS's client-list.json * ```ID: 101```, LotATC's stats.json +# Project information ## Built With * [VisualStudio 2017 Community](https://visualstudio.microsoft.com/vs/community/) * [Notepad++](https://notepad-plus-plus.org/) -* [TortoiseGit](https://tortoisegit.org/) + +## used 3rd party resources + +* [Tango Icon Library](http://tango.freedesktop.org/Tango_Icon_Library) ## Contributing