20 Commits

Author SHA1 Message Date
Szymon Porwolik
f49734560e Formated code , updated MySQL structure 2019-02-25 00:00:43 +01:00
Szymon Porwolik
5d3f7148bb Added Stats [WIP], new approach for issue #1 , Added logins, Added category decoding. 2019-02-24 23:24:24 +01:00
Szymon Porwolik
2629295f93 Merge branch 'master' of https://github.com/szporwolik/perun 2019-02-24 21:19:04 +01:00
Szymon Porwolik
a6ad17dbe1 Fixed issue with "blinking" SRS status when no clients connected to server. 2019-02-24 21:18:44 +01:00
simpo
b7022c22c1 Update README.md 2019-02-24 20:27:50 +01:00
Szymon Porwolik
907d8d01d6 Added weather and coalition export. 2019-02-24 20:27:17 +01:00
Szymon Porwolik
fc82c43072 Fixed issue #1 testing required. 2019-02-24 19:53:43 +01:00
Szymon Porwolik
37b6f3419e Merge branch 'master' of https://github.com/szporwolik/perun 2019-02-24 19:28:14 +01:00
Szymon Porwolik
b96affd4fd Build and publication update - app will now deploy to remote FTP and generate one click installer. 2019-02-24 19:28:00 +01:00
simpo
8d733f83ab Update README.md
Added VS OneClick http addres for quick deployment.
2019-02-24 19:24:12 +01:00
Szymon Porwolik
58cc8a7b39 Updated MySQL scheme to match latest changes in Lua 2019-02-24 17:34:31 +01:00
Szymon Porwolik
e09926aa80 Fixed and upgraded event handlers.
System will store DCS server time for events and chat logs.
2019-02-24 17:17:44 +01:00
Szymon Porwolik
13969a95cc Merge branch 'master' of https://github.com/szporwolik/perun 2019-02-24 00:17:55 +01:00
Szymon Porwolik
5c9fa4e284 v0.3.2 2019-02-24 00:17:20 +01:00
Szymon Porwolik
3512f7f5cf - motd will not be logged to chat log
- mission data will be added to json
2019-02-24 00:15:08 +01:00
simpo
6847a1e262 Update README.md 2019-02-23 23:41:49 +01:00
simpo
c917d0ef04 Update README.md 2019-02-23 22:44:04 +01:00
simpo
784ad9947f Update README.md 2019-02-23 22:19:42 +01:00
simpo
91c629ed81 Update README.md 2019-02-23 22:16:29 +01:00
Szymon Porwolik
5d415812fa Added SQL to create MySQL database. 2019-02-23 22:05:08 +01:00
9 changed files with 623 additions and 309 deletions

View File

@@ -7,7 +7,8 @@
-- ########### SETTINGS ###########
Perun.Refresh = 15 -- base refresh rate in secounds (values lower than 60 may affect performance!)
Perun.RefreshStatus = 15 -- base refresh rate in seconds to send status update (values lower than 60 may affect performance!)
Perun.RefreshMission = 60 -- refresh rate in seconds to send mission information (values lower than 60 may affect performance!)
Perun.JsonLocation = "Scripts\\Json\\perun_export.json" -- relatve do user's SaveGames DCS folder
Perun.UDPTargetPort = 48620 -- UDP port to send data to
Perun.MOTD_L1 = "Witamy na serwerze Gildia.org !" -- Message send to players connecting the server - Line 1
@@ -16,11 +17,14 @@
-- ########### END OF SETTINGS ###########
-- Variable init
Perun.Version = "v0.3.0"
Perun.Version = "v0.3.5"
Perun.StatusData = {}
Perun.SlotsData = {}
Perun.MissionData = {}
Perun.VersionData = {}
Perun.lastSent =0
Perun.MissionHash=""
Perun.lastSentStatus =0
Perun.lastSentMission =0
Perun.JsonLocation = lfs.writedir() .. Perun.JsonLocation
Perun.socket = require("socket")
Perun.UDP = assert(Perun.socket.udp())
@@ -29,6 +33,33 @@
Perun.UDP:setpeername("127.0.0.1",Perun.UDPTargetPort)
-- Function definition
Perun.GetCategory = function(id)
-- via https://pastebin.com/GUAXrd2U
local _killed_target_category = DCS.getUnitTypeAttribute(id, "category")
if _killed_target_category == nil then
local _killed_target_cat_check_ship = DCS.getUnitTypeAttribute(id, "DeckLevel")
local _killed_target_cat_check_plane = DCS.getUnitTypeAttribute(id, "WingSpan")
if _killed_target_cat_check_ship ~= nil and _killed_target_cat_check_plane == nil then
_killed_target_category = "Ships"
elseif _killed_target_cat_check_ship == nil and _killed_target_cat_check_plane ~= nil then
_killed_target_category = "Planes"
else
_killed_target_category = "Helicopters"
end
end
return _killed_target_category
end
Perun.SideID2Name = function(id)
-- Helper function
local sides = {
[0] = 'SPECTATOR',
[1] = 'RED',
[2] = 'BLUE',
}
return sides[id]
end
Perun.AddLog = function(text)
-- Adds logs to DCS.log file
net.log("Perun : ".. text)
@@ -40,6 +71,8 @@
TempData["1"]=Perun.VersionData
TempData["2"]=Perun.StatusData
TempData["3"]=Perun.SlotsData
TempData["4"]=Perun.MissionData
TempData["debug"]=net.get_player_list()
io.open(Perun.JsonLocation,"w"):close()
perun_export = io.open(Perun.JsonLocation, "w")
@@ -84,23 +117,26 @@
temp['realtime']=DCS.getRealTime()
temp['pause']=DCS.getPause()
temp['multiplayer']=DCS.isMultiplayer()
temp['theatre'] = Perun.MissionData['mission']['theatre']
temp['weather'] = Perun.MissionData['mission']['weather']
Perun.UpdateStatusPart("mission",temp)
-- 2 - Players
temp = net.get_player_list()
for _, i in ipairs(temp) do
temp[i]=net.get_player_info(i)
_temp = net.get_player_list()
_temp2={}
for _, i in pairs(_temp) do
_temp2[i]=net.get_player_info(i)
end
Perun.UpdateStatusPart("players",temp)
Perun.UpdateStatusPart("players",_temp2)
-- Send
Perun.Send(2,Perun.StatusData)
end
Perun.UpdateMission = function()
-- Main function for mission information updates
Perun.UpdateSlots = function()
-- Main function for slot
-- Update Mission data
-- Update slots data
Perun.SlotsData['coalitions']=DCS.getAvailableCoalitions()
Perun.SlotsData['slots']={}
@@ -111,6 +147,16 @@
Perun.Send(3,Perun.SlotsData)
end
Perun.UpdateMission = function()
-- Main function for mission information updates
-- Update Mission data
Perun.MissionData=DCS.getCurrentMission()
-- Send
-- Perun.Send(4,Perun.MissionData)
end
Perun.LogChat = function(playerID,msg,all)
-- Log chat messages
@@ -118,6 +164,8 @@
data['player']= net.get_player_info(playerID, "name")
data['msg']=msg
data['all']=all
data['datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['log_missionhash']=Perun.MissionHash
Perun.Send(50,data)
end
@@ -128,20 +176,81 @@
data={}
data['log_type']= log_type
data['log_content']=log_content
data['log_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['log_missionhash']=Perun.MissionHash
Perun.Send(51,data)
end
Perun.LogStats = function(playerID)
-- Log player status
-- TBD : not working at the moment WIP
p_stats={}
p_stats['PS_CAR']=net.get_stat(playerID,2)
p_stats['PS_PLANE']=net.get_stat(playerID,3)
p_stats['PS_SHIP']=net.get_stat(playerID,4)
p_stats['PS_SCORE']=net.get_stat(playerID,5)
p_stats['PS_LAND']=net.get_stat(playerID,6)
p_stats['PS_PING']=net.get_stat(playerID,0)
p_stats['PS_CRASH']=net.get_stat(playerID,1)
p_stats['PS_EJECT']=net.get_stat(playerID,7)
p_stats['debug']="ok"
data={}
data['stat_data']=p_stats
data['stat_ucid']=net.get_player_info(playerID, 'ucid')
data['stat_datetime']=os.date('%Y-%m-%d %H:%M:%S')
data['stat_missionhash']=Perun.MissionHash
Perun.Send(52,data)
end
Perun.LogLogin = function(playerID)
-- Player logged in
data={}
data['login_ucid']=net.get_player_info(playerID, 'ucid')
data['login_ipaddr']=net.get_player_info(playerID, 'ipaddr')
data['login_name']=net.get_player_info(playerID, 'name')
data['login_datetime']=os.date('%Y-%m-%d %H:%M:%S')
Perun.Send(53,data)
end
--- Event callbacks
Perun.onSimulationStart = function()
Perun.MissionHash=DCS.getMissionName( ).."@"..os.date('%Y%m%d_%H%M%S');
Perun.LogEvent("SimStart",Perun.MissionHash);
end
Perun.onSimulationStop = function()
Perun.LogEvent("SimStop",Perun.MissionHash);
end
Perun.onPlayerDisconnect= function(id, err_code)
Perun.LogEvent("disconnect", "Player " .. net.get_player_info(id, "name") .. " disconnected; " .. err_code);
end
Perun.onSimulationFrame = function()
local _now = DCS.getRealTime()
if _now > Perun.lastSent + Perun.Refresh then
Perun.lastSent = _now
-- Send status update
if _now > Perun.lastSentStatus + Perun.RefreshStatus then
Perun.lastSentStatus = _now
Perun.UpdateMission()
Perun.UpdateStatus()
Perun.UpdateVersion()
Perun.UpdateJson()
end
-- Send mission update
if _now > Perun.lastSentMission + Perun.RefreshMission then
Perun.lastSentMission = _now
Perun.UpdateSlots()
Perun.UpdateMission()
Perun.UpdateJson()
end
@@ -149,6 +258,8 @@
Perun.onMissionLoadEnd = function()
Perun.UpdateMission()
Perun.UpdateSlots()
Perun.UpdateVersion()
Perun.UpdateJson()
end
@@ -158,60 +269,104 @@
end
Perun.onPlayerTrySendChat = function (playerID, msg, all)
Perun.LogChat(playerID,msg,all)
if msg~=Perun.MOTD_L1 and msg~=Perun.MOTD_L2 then
Perun.LogChat(playerID,msg,all)
end
return msg
end
Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4)
Perun.onGameEvent = function (eventName,arg1,arg2,arg3,arg4,arg5,arg6,arg7)
if eventName == "friendly_fire" then
--"friendly_fire", playerID, weaponName, victimPlayerID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name").." killed " .. net.get_player_info(arg3, "name") .. " using " .. arg2);
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name").." killed friendy " .. net.get_player_info(arg3, "name") .. " using " .. arg2);
Perun.LogStats(arg1);
elseif eventName == "mission_end" then
--"mission_end", winner, msg
Perun.LogEvent(eventName,"Mission end, winner " .. arg1 .. " message: " .. arg2);
Perun.LogEvent(eventName,"Mission finished, winner " .. arg1 .. " message: " .. arg2);
elseif eventName == "kill" then
--"kill", killerPlayerID, killerUnitType, killerSide, victimPlayerID, victimUnitType, victimSide, weaponName
Perun.LogEvent(eventName,net.get_player_info(arg1, "name").. " in " .. arg3 .. " " .. arg2 .. " killed " .. net.get_player_info(arg4, "name") .. " in " .. arg6 .. " " .. arg5 .. " using " .. arg7);
if net.get_player_info(arg4, "name") ~= nil then
_temp = " player ".. net.get_player_info(arg4, "name") .." ";
Perun.LogStats(arg4);
else
_temp = " AI ";
end
if net.get_player_info(arg1, "name") ~= nil then
_temp2 = " player ".. net.get_player_info(arg1, "name") .." ";
Perun.LogStats(arg1);
else
_temp2 = " AI ";
end
Perun.LogEvent(eventName,Perun.SideID2Name(arg3) .. _temp2 .. " in " .. arg2 .. " killed " .. Perun.SideID2Name(arg6) .. _temp .. " in " .. arg5 .. " using " .. arg7 .. " [".. Perun.GetCategory(arg5).."]");
elseif eventName == "self_kill" then
--"self_kill", playerID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " killed himself");
Perun.LogStats(arg1);
elseif eventName == "change_slot" then
--"change_slot", playerID, slotID, prevSide
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " changed slot to " .. arg2);
if DCS.getUnitType(arg2) ~= nil and DCS.getUnitType(arg2) ~= "" then
_temp = DCS.getUnitType(arg2);
else
_temp = "SPECTATOR";
end
Perun.LogEvent(eventName,Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " changed slot to " .. _temp);
Perun.LogStats(arg1);
elseif eventName == "connect" then
--"connect", playerID, name
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " connected");
Perun.LogLogin(arg1);
Perun.LogEvent(eventName,"Player "..net.get_player_info(arg1, "name") .. " connected");
elseif eventName == "disconnect" then
--"disconnect", playerID, name, playerSide, reason_code
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " disconnected");
Perun.LogEvent(eventName, Perun.SideID2Name(arg3) .. " player " ..net.get_player_info(arg1, "name") .. " disconnected");
Perun.LogStats(arg1);
elseif eventName == "crash" then
--"crash", playerID, unit_missionID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " crashed");
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " crashed in " .. DCS.getUnitType(arg2));
Perun.LogStats(arg1);
elseif eventName == "eject" then
--"eject", playerID, unit_missionID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " ejected");
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " ejected " .. DCS.getUnitType(arg2));
Perun.LogStats(arg1);
elseif eventName == "takeoff" then
--"takeoff", playerID, unit_missionID, airdromeName
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " took off from " .. arg3);
if arg3 then
_temp = " from " .. arg3;
else
_temp = "";
end
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " took off in ".. DCS.getUnitType(arg2) .. _temp);
Perun.LogStats(arg1);
elseif eventName == "landing" then
--"landing", playerID, unit_missionID, airdromeName
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " landed at " .. arg3);
if arg3 then
_temp = " at " .. arg3;
else
_temp ="";
end
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " landed in " .. DCS.getUnitType(arg2).. _temp);
Perun.LogStats(arg1);
elseif eventName == "pilot_death" then
--"pilot_death", playerID, unit_missionID
Perun.LogEvent(eventName,net.get_player_info(arg1, "name") .. " died");
Perun.LogEvent(eventName, Perun.SideID2Name( net.get_player_info(arg1, "side")) .. " player " .. net.get_player_info(arg1, "name") .. " in " .. DCS.getUnitType(arg2) .. " died");
Perun.LogStats(arg1);
else
Perun.LogEvent(eventName,"Unknown event type");

View File

@@ -36,7 +36,7 @@
<value>False</value>
</setting>
<setting name="MYSQL_Port" serializeAs="String">
<value />
<value>3306</value>
</setting>
</Perun_v1.Properties.Settings>
<Perun.Properties.Settings>

View File

@@ -12,21 +12,30 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<IsWebBootstrapper>false</IsWebBootstrapper>
<PublishUrl>C:\Users\simpo\Desktop\Perun\</PublishUrl>
<IsWebBootstrapper>true</IsWebBootstrapper>
<PublishUrl>ftp://s18.mydevil.net/perun/</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<InstallFrom>Web</InstallFrom>
<UpdateEnabled>true</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<AutorunEnabled>true</AutorunEnabled>
<ApplicationRevision>1</ApplicationRevision>
<ApplicationVersion>0.3.0.%2a</ApplicationVersion>
<InstallUrl>http://share.porwolik.com/ftp/perun/</InstallUrl>
<SupportUrl>https://github.com/szporwolik/perun</SupportUrl>
<ErrorReportUrl>https://github.com/szporwolik/perun</ErrorReportUrl>
<TargetCulture>en</TargetCulture>
<ProductName>Perun for DCS World</ProductName>
<PublisherName>szporwolik</PublisherName>
<SuiteName>Perun</SuiteName>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>Perun.htm</WebPage>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>0.3.5.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<CreateDesktopShortcut>true</CreateDesktopShortcut>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
</PropertyGroup>
@@ -73,6 +82,7 @@
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<PropertyGroup />
<PropertyGroup>
<ApplicationManifest>Properties\app.manifest</ApplicationManifest>
</PropertyGroup>

View File

@@ -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.3.0.0")]
[assembly: AssemblyFileVersion("0.3.0.0")]
[assembly: AssemblyVersion("0.3.5.0")]
[assembly: AssemblyFileVersion("0.3.5.0")]
[assembly: NeutralResourcesLanguage("en")]

View File

@@ -121,7 +121,7 @@ namespace Perun_v1.Properties {
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("")]
[global::System.Configuration.DefaultSettingValueAttribute("3306")]
public string MYSQL_Port {
get {
return ((string)(this["MYSQL_Port"]));

View File

@@ -27,7 +27,7 @@
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="MYSQL_Port" Type="System.String" Scope="User">
<Value Profile="(Default)" />
<Value Profile="(Default)">3306</Value>
</Setting>
</Settings>
</SettingsFile>

View File

@@ -17,12 +17,13 @@ namespace Perun_v1
{
// Variable definitions
public Thread thread_UDPListener; // Seperate thread for UDP
public class_UDPListener UDPListener; // Helper class for UDP comunication
public string[] LogHistory=new string[10]; // Log history for GUI
public string[] SendBuffer=new string[10]; // Mysql send buffer
public bool LetMeOut=false; // Helper to handle system tray
public string MySql_connStr; // MySQL connection string
public Thread thread_UDPListener; // Seperate thread for UDP
public class_UDPListener UDPListener; // Helper class for UDP comunication
public string[] LogHistory = new string[10]; // Log history for GUI
public string[] SendBuffer = new string[10]; // Mysql send buffer
public bool LetMeOut = false; // Helper to handle system tray
public string MySql_connStr; // MySQL connection string
public string publishVersion = "DEBUG"; // Helper for pulling version definition
public static void LogHistoryAdd(ref string[] LogHistory, string Comment)
{
@@ -37,62 +38,75 @@ namespace Perun_v1
public void SendToMySql(string raw_udp_frame)
{
// Main function to send data to mysql
dynamic udp_frame = JsonConvert.DeserializeObject(raw_udp_frame);
dynamic udp_frame = JsonConvert.DeserializeObject(raw_udp_frame);
// Cut raw data to type and paylod for proper mysql insert
string type = udp_frame.type;
string payload = "";
string sql = "";
string type = udp_frame.type;
string payload = "";
string sql = "";
// Modify specific
// Modify specific
if (type == "1") // Inject app version information
{
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
string version = fileVersionInfo.ProductVersion;
udp_frame.payload["v_win"] = "v"+version;
}
{
udp_frame.payload["v_win"] = "v" + publishVersion;
}
// Specific SQL
if(type == "50")
{
sql = "INSERT INTO `pe_LogChat` (`pe_LogChat_id`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`) VALUES (NULL, '"+udp_frame.payload.player+ "', '" + udp_frame.payload.msg + "', '" + udp_frame.payload.all + "');";
}
else if(type == "51")
{
sql = "INSERT INTO `pe_LogEvent` (`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`) VALUES (NULL, CURRENT_TIMESTAMP, '" + udp_frame.payload.log_type + "', '" + udp_frame.payload.log_content + "');";
}
else
{
payload = JsonConvert.SerializeObject(udp_frame.payload);
sql = "INSERT INTO pe_DataRaw(pe_dataraw_type,pe_dataraw_payload) VALUES (" + type + ",JSON_QUOTE('" + payload + "')) ON DUPLICATE KEY UPDATE pe_dataraw_payload = JSON_QUOTE('" + payload + "')";
}
// Specific SQL
if (type == "50")
{
// Add entry to event log
sql = "INSERT INTO `pe_LogChat` (`pe_LogChat_id`,`pe_LogChat_datetime`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`) VALUES (NULL,'" + udp_frame.payload.datetime + "', '" + udp_frame.payload.player + "', '" + udp_frame.payload.msg + "', '" + udp_frame.payload.all + "');";
}
else if (type == "51")
{
// Add entry to event log
sql = "INSERT INTO `pe_LogEvent` (`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`,`pe_LogEvent_missionhash`) VALUES ( NULL, '" + udp_frame.payload.log_datetime + "', '" + udp_frame.payload.log_type + "', '" + udp_frame.payload.log_content + "', '" + udp_frame.payload.log_missionhash + "');";
}
else if (type == "52")
{
// Update user stats
payload = JsonConvert.SerializeObject(udp_frame.payload.stat_data);
sql = "INSERT INTO `pe_LogStats` (`pe_LogStats_datetime`, `pe_LogStats_ucid`, `pe_LogStats_debug`,`pe_LogStats_missionhash`) VALUES ('" + udp_frame.payload.stat_datetime + "', '" + udp_frame.payload.stat_ucid + "', JSON_QUOTE('" + payload + "'), '" + udp_frame.payload.stat_missionhash + "') ON DUPLICATE KEY UPDATE pe_LogStats_datetime='" + udp_frame.payload.stat_datetime + "',pe_LogStats_ucid = '" + udp_frame.payload.stat_ucid + "', pe_LogStats_debug=JSON_QUOTE('" + payload + "'), pe_LogStats_missionhash='" + udp_frame.payload.stat_missionhash + "'";
}
else if (type == "53")
{
// User logged in to DCS server
payload = JsonConvert.SerializeObject(udp_frame.payload.stat_data);
sql = "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_ucid`, `pe_LogLogins_name`, `pe_LogLogins_ip`) VALUES ('" + udp_frame.payload.login_datetime + "', '" + udp_frame.payload.login_ucid + "', '" + udp_frame.payload.login_name + "', '" + udp_frame.payload.login_ipaddr + "');";
sql = sql + "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_id`, `pe_DataPlayers_ucid`, `pe_DataPlayers_lastip`, `pe_DataPlayers_lastname`, `pe_DataPlayers_updated`) VALUES (NULL, '" + udp_frame.payload.login_ucid + "', '" + udp_frame.payload.login_ipaddr + "', '" + udp_frame.payload.login_name + "', '" + udp_frame.payload.login_datetime + "') ON DUPLICATE KEY UPDATE pe_DataPlayers_lastip='" + udp_frame.payload.login_ipaddr + "',pe_DataPlayers_lastname='" + udp_frame.payload.login_name + "',pe_DataPlayers_updated='" + udp_frame.payload.login_datetime + "'";
}
else
{
// General definition used for 1-10 packets
payload = JsonConvert.SerializeObject(udp_frame.payload);
sql = "INSERT INTO pe_DataRaw(pe_dataraw_type,pe_dataraw_payload) VALUES (" + type + ",JSON_QUOTE('" + payload + "')) ON DUPLICATE KEY UPDATE pe_dataraw_payload = JSON_QUOTE('" + payload + "')";
}
// Connect to mysql
// Connect to mysql and execute sql
MySqlConnection conn = new MySqlConnection(MySql_connStr);
try
try
{
Console.WriteLine("Sending data to MySQL - Begin");
conn.Open();
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine("Sending data to MySQL - Begin");
conn.Open();
MySqlCommand cmd = new MySqlCommand(sql, conn);
MySqlDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine(rdr[0] + " -- " + rdr[1]);
}
rdr.Close();
LogHistoryAdd(ref LogHistory, "MySQL updated, package type: "+ type);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
LogHistoryAdd(ref LogHistory, "ERROR: MySQL");
Console.WriteLine(rdr[0] + " -- " + rdr[1]);
}
rdr.Close();
LogHistoryAdd(ref LogHistory, "MySQL updated, package type: " + type);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
LogHistoryAdd(ref LogHistory, "ERROR: MySQL");
}
conn.Close();
Console.WriteLine("Sending data to MySQL - Done");
conn.Close();
Console.WriteLine("Sending data to MySQL - Done");
}
@@ -100,74 +114,73 @@ namespace Perun_v1
public class class_UDPListener
{
// Main class for UDP listener
int listenPort; // Port to listen at
public bool done; // Helper to exit main loop without killing thread
public UdpClient listener; // Listener object
public string[] LogHistory; // Log history for GUI
public string[] SendBuffer; // Mysql send buffer
int listenPort; // Port to listen at
public bool done; // Helper to exit main loop without killing thread
public UdpClient listener; // Listener object
public string[] LogHistory; // Log history for GUI
public string[] SendBuffer; // Mysql send buffer
public class_UDPListener(int port, ref string[] LogHistory, ref string[] SendBuffer)
{
// Create clas - NOTE that there is reference passing
this.listenPort = port;
this.LogHistory = LogHistory;
this.SendBuffer = SendBuffer;
}
public void StartListen()
{
// Start listening to UDP
this.done = false;
listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Loopback, listenPort);
string received_data;
byte[] receive_byte_array;
Console.WriteLine("UDP Listen start");
try
{
while (!done)
{
Console.WriteLine("UDP: Waiting for packet");
receive_byte_array = listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
Console.WriteLine("Sender: {0} Payload: {1}", groupEP.ToString(), received_data);
// Add to log history and rotate
dynamic udp_frame = JsonConvert.DeserializeObject(received_data);
string type = udp_frame.type;
LogHistoryAdd(ref LogHistory, "UDP packet received, type: "+ type);
// Add to mySQL send buffer and rotate
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
SendBuffer[i] = SendBuffer[i + 1];
}
SendBuffer[9] = received_data;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("UDP listen stop");
listener.Close();
}
public class_UDPListener(int port, ref string[] LogHistory, ref string[] SendBuffer)
{
// Create clas - NOTE that there is reference passing
this.listenPort = port;
this.LogHistory = LogHistory;
this.SendBuffer = SendBuffer;
}
public void StartListen()
{
// Start listening to UDP
this.done = false;
listener = new UdpClient(listenPort);
IPEndPoint groupEP = new IPEndPoint(IPAddress.Loopback, listenPort);
string received_data;
byte[] receive_byte_array;
Console.WriteLine("UDP Listen start");
try
{
while (!done)
{
Console.WriteLine("UDP: Waiting for packet");
receive_byte_array = listener.Receive(ref groupEP);
received_data = Encoding.ASCII.GetString(receive_byte_array, 0, receive_byte_array.Length);
Console.WriteLine("Sender: {0} Payload: {1}", groupEP.ToString(), received_data);
// Add to log history and rotate
dynamic udp_frame = JsonConvert.DeserializeObject(received_data);
string type = udp_frame.type;
LogHistoryAdd(ref LogHistory, "UDP packet received, type: " + type);
// Add to mySQL send buffer and rotate
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
SendBuffer[i] = SendBuffer[i + 1];
}
SendBuffer[9] = received_data;
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("UDP listen stop");
listener.Close();
}
}
public form_Main()
{
// Form init
InitializeComponent();
InitializeComponent();
}
private void form_Main_Load(object sender, EventArgs e)
{
// Form loaded - fill controls with default values
LogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun loaded...";
LogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun loaded...";
// Load settings
con_txt_mysql_database.Text = Properties.Settings.Default.MYSQL_DB;
@@ -181,32 +194,119 @@ namespace Perun_v1
con_check_3rd_srs.Checked = Properties.Settings.Default.OTHER_SRS_USE;
// Version to title header
Assembly assembly = Assembly.GetExecutingAssembly();
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
this.Text = this.Text + " - v" + fileVersionInfo.ProductVersion;
if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
{
System.Deployment.Application.ApplicationDeployment cd = System.Deployment.Application.ApplicationDeployment.CurrentDeployment;
publishVersion = cd.CurrentVersion.ToString();
}
this.Text = this.Text + " - v" + publishVersion;
}
private void con_Button_Listen_ON_Click(object sender, EventArgs e)
{
// Start listening
UDPListener = new class_UDPListener(48620,ref LogHistory, ref SendBuffer);
thread_UDPListener = new Thread(UDPListener.StartListen);
thread_UDPListener.Start();
UDPListener = new class_UDPListener(48620, ref LogHistory, ref SendBuffer);
thread_UDPListener = new Thread(UDPListener.StartListen);
thread_UDPListener.Start();
// Update form controls
con_Button_Listen_ON.Enabled = false;
con_Button_Listen_OFF.Enabled = true;
con_txt_mysql_database.Enabled = false;
con_txt_mysql_username.Enabled = false;
con_txt_mysql_password.Enabled = false;
con_txt_mysql_server.Enabled = false;
con_txt_mysql_port.Enabled = false;
con_txt_3rd_lotatc.Enabled = false;
con_txt_3rd_srs.Enabled = false;
con_check_3rd_lotatc.Enabled = false;
con_check_3rd_srs.Enabled = false;
con_Button_Listen_ON.Enabled = false;
con_Button_Listen_OFF.Enabled = true;
con_txt_mysql_database.Enabled = false;
con_txt_mysql_username.Enabled = false;
con_txt_mysql_password.Enabled = false;
con_txt_mysql_server.Enabled = false;
con_txt_mysql_port.Enabled = false;
con_txt_3rd_lotatc.Enabled = false;
con_txt_3rd_srs.Enabled = false;
con_check_3rd_lotatc.Enabled = false;
con_check_3rd_srs.Enabled = false;
// Save settings
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
Properties.Settings.Default.MYSQL_Password = con_txt_mysql_password.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_server.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.OTHER_LOTATC_FILE = con_txt_3rd_lotatc.Text;
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;
// Prepare connection string
MySql_connStr = "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_1000ms.Enabled = true;
tim_10000ms.Enabled = true;
}
private void con_Button_Listen_OFF_Click(object sender, EventArgs e)
{
// Stop listening
UDPListener.listener.Close();
// Update form 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;
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;
// Stop timmers
tim_1000ms.Enabled = false;
tim_10000ms.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
// Main timer to sync GUI with background tasks and flush buffers
// Refresh Log Window
con_List_Received.Items.Clear();
foreach (string i in LogHistory)
{
if (i != null)
{
con_List_Received.Items.Add(i);
}
}
// Send buffer to MySQL
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
if (SendBuffer[i] != null)
{
SendToMySql(SendBuffer[i]);
SendBuffer[i] = null;
}
}
}
private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
// Open default browser with link to Perun repo
ProcessStartInfo sInfo = new ProcessStartInfo("https://github.com/szporwolik/perun");
Process.Start(sInfo);
}
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Close app
DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
// Save settings on exit
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
@@ -219,104 +319,20 @@ namespace Perun_v1
Properties.Settings.Default.OTHER_LOTATC_USE = con_check_3rd_lotatc.Checked;
Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked;
// Prepare connection string
MySql_connStr = "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;
Properties.Settings.Default.Save();
// Start timmers
tim_1000ms.Enabled = true;
tim_10000ms.Enabled = true;
}
private void con_Button_Listen_OFF_Click(object sender, EventArgs e)
{
// Stop listening
UDPListener.listener.Close();
// Update form 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;
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;
// Stop timmers
tim_1000ms.Enabled = false;
tim_10000ms.Enabled = false;
}
private void timer1_Tick(object sender, EventArgs e)
{
// Main timer to sync GUI with background tasks and flush buffers
// Refresh Log Window
con_List_Received.Items.Clear();
foreach (string i in LogHistory)
{
if (i != null)
{
con_List_Received.Items.Add(i);
}
}
// Send buffer to MySQL
for (int i = 0; i < SendBuffer.Length - 1; i++)
{
if (SendBuffer[i] != null)
{
SendToMySql(SendBuffer[i]);
SendBuffer[i] = null;
}
}
}
private void con_lab_github_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
// Open default browser with link to Perun repo
ProcessStartInfo sInfo = new ProcessStartInfo("https://github.com/szporwolik/perun");
Process.Start(sInfo);
}
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Close app
DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes)
{
// Save settings on exit
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_DB = con_txt_mysql_database.Text;
Properties.Settings.Default.MYSQL_User = con_txt_mysql_username.Text;
Properties.Settings.Default.MYSQL_Password = con_txt_mysql_password.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.MYSQL_Server = con_txt_mysql_server.Text;
Properties.Settings.Default.MYSQL_Port = con_txt_mysql_port.Text;
Properties.Settings.Default.OTHER_LOTATC_FILE = con_txt_3rd_lotatc.Text;
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.Save();
LetMeOut = true;
this.Close();
}
else if (dialogResult == DialogResult.No)
{
//do nothing
}
LetMeOut = true;
this.Close();
}
else if (dialogResult == DialogResult.No)
{
//do nothing
}
}
private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
{
// Minimize to try
// Minimize to try
if (e.CloseReason == CloseReason.UserClosing && !LetMeOut)
{
e.Cancel = true;
@@ -344,7 +360,8 @@ namespace Perun_v1
{
con_txt_3rd_srs.Text = openFileDialog_SRS.FileName;
con_check_3rd_srs.Checked = true;
} else
}
else
{
con_txt_3rd_srs.Text = "";
con_check_3rd_srs.Checked = false;
@@ -369,8 +386,8 @@ namespace Perun_v1
private void tim_10000ms_Tick(object sender, EventArgs e)
{
// Main timer to send JSON files to MySQL
string strSRSJson ="";
string strLotATCJson="";
string strSRSJson = "";
string strLotATCJson = "";
bool SRSdefault = true;
bool LotATCdefault = true;
@@ -386,32 +403,43 @@ namespace Perun_v1
for (int i = 0; i < raw_lotatc.Count; i++)
{
int temp = raw_lotatc[i].RadioInfo.radios.Count - 1;
for (int j = temp; j >= 0; j--)
if (raw_lotatc[i].RadioInfo != null)
{
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")
int temp = raw_lotatc[i].RadioInfo.radios.Count - 1;
for (int j = temp; j >= 0; j--)
{
raw_lotatc[i].RadioInfo.radios[j].Remove();
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();
}
raw_lotatc[i].ClientChannelId.Parent.Remove();
raw_lotatc[i].RadioInfo.simultaneousTransmission.Parent.Remove();
}
strSRSJson = JsonConvert.SerializeObject(raw_lotatc);
strSRSJson = "{'type':'100','payload':'" + strSRSJson + "'}";
if (raw_lotatc.Count > 0)
{
strSRSJson = JsonConvert.SerializeObject(raw_lotatc);
strSRSJson = "{'type':'100','payload':'" + strSRSJson + "'}";
}
else
{
strSRSJson = "{'type':'100','payload':{'ignore':'false'}}";
}
SRSdefault = false;
LogHistoryAdd(ref LogHistory, "SRS data loaded");
@@ -423,7 +451,7 @@ namespace Perun_v1
}
if(SRSdefault)
if (SRSdefault)
{
strSRSJson = "{'type':'100','payload':{'ignore':'true'}}";
}

116
03_MySQL/m1081_perun.sql Normal file
View File

@@ -0,0 +1,116 @@
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET AUTOCOMMIT = 0;
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Baza danych: `m1081_perun`
--
CREATE DATABASE IF NOT EXISTS `m1081_perun` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
USE `m1081_perun`;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_DataPlayers`
--
DROP TABLE IF EXISTS `pe_DataPlayers`;
CREATE TABLE IF NOT EXISTS `pe_DataPlayers` (
`pe_DataPlayers_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_DataPlayers_ucid` varchar(150) NOT NULL,
`pe_DataPlayers_lastip` varchar(100) NOT NULL,
`pe_DataPlayers_lastname` varchar(150) NOT NULL,
`pe_DataPlayers_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_DataPlayers_id`),
UNIQUE KEY `UNIQUE_UCID` (`pe_DataPlayers_ucid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_DataRaw`
--
DROP TABLE IF EXISTS `pe_DataRaw`;
CREATE TABLE IF NOT EXISTS `pe_DataRaw` (
`pe_dataraw_type` tinyint(4) NOT NULL AUTO_INCREMENT,
`pe_dataraw_payload` text NOT NULL,
`pe_dataraw_updated` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`pe_dataraw_type`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogChat`
--
DROP TABLE IF EXISTS `pe_LogChat`;
CREATE TABLE IF NOT EXISTS `pe_LogChat` (
`pe_LogChat_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogChat_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pe_LogChat_playerid` varchar(100) NOT NULL,
`pe_LogChat_msg` text NOT NULL,
`pe_LogChat_all` varchar(10) NOT NULL,
PRIMARY KEY (`pe_LogChat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogEvent`
--
DROP TABLE IF EXISTS `pe_LogEvent`;
CREATE TABLE IF NOT EXISTS `pe_LogEvent` (
`pe_LogEvent_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogEvent_missionhash` varchar(150) DEFAULT NULL,
`pe_LogEvent_datetime` datetime DEFAULT CURRENT_TIMESTAMP,
`pe_LogEvent_type` varchar(100) NOT NULL,
`pe_LogEvent_content` text NOT NULL,
PRIMARY KEY (`pe_LogEvent_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogLogins`
--
DROP TABLE IF EXISTS `pe_LogLogins`;
CREATE TABLE IF NOT EXISTS `pe_LogLogins` (
`pe_LogLogins_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pe_LogLogins_ucid` varchar(150) NOT NULL,
`pe_LogLogins_name` varchar(150) NOT NULL,
`pe_LogLogins_ip` varchar(100) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Struktura tabeli dla tabeli `pe_LogStats`
--
DROP TABLE IF EXISTS `pe_LogStats`;
CREATE TABLE IF NOT EXISTS `pe_LogStats` (
`pe_LogStats_id` bigint(20) NOT NULL AUTO_INCREMENT,
`pe_LogStats_missionhash` varchar(150) DEFAULT NULL,
`pe_LogStats_datetime` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`pe_LogStats_ucid` varchar(200) NOT NULL,
`pe_LogStats_debug` text,
PRIMARY KEY (`pe_LogStats_id`),
UNIQUE KEY `UNIQUE_STATS_PER_MISSION_AND_UCID` (`pe_LogStats_ucid`,`pe_LogStats_missionhash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@@ -1,11 +1,13 @@
# Perun for DCS World
This toolset extracts data from DCS World server and export it to local json file and UDP port. **Optional** windows app puts JSON data to MySQL database.
Additionaly windows app can be used to merge LotATC and DCS SRS data in one database making Perun for DCS World ultimate integration tool for server admins.
This toolset extracts data from DCS World server and sends information to the local Json file and UDP port.
## Getting Started
Provided windows app puts JSON data to MySQL database. Additionaly Perun windows app 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.
You can use this toolkit with or without Windows app. Simple DCS export scripts will create JSON file which can be used for further processing, by default this file is created in Scripts\Json folder located in your Saved Games DCS folder tree.
However this software is intended to be used by experienced users - the output is data Json and MySQL; you will need to process/display it yourself.
![Perun in action](https://i.imgur.com/ougQMPq.png)
![Data flow](https://i.imgur.com/sHDQoLM.png)
### Prerequisites
@@ -16,33 +18,36 @@ Core:
* MySQL server with read/write access
3rd party support:
* for [DCS SRS](https://github.com/ciribob/DCS-SimpleRadioStandalone/releases) integration location of the clients-list.json file and SRS configuration with JSON data export enabled - see [SRS documentation](https://github.com/ciribob/DCS-SimpleRadioStandalone/wiki)
* for [LotATC](https://www.lotatc.com/) integration location of the stats.json file and LotATC configuration with JSON data export enabled - see [LotATC documentation](https://www.lotatc.com/documentation/server_configuration.html)
* 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
* Download latest [release](https://github.com/szporwolik/perun/releases) **optionaly** together with Win32 binary file for MySQL export
* Copy contents of DCS folder to you \Scripts folder (inside DCS folder in your Saved Games)
* create MySQL server 03_MySQL folder contains creation SQL file
* Download latest [release](https://github.com/szporwolik/perun/releases), **optionaly** together with Win32 binary file for MySQL export - [DOWNLOAD](http://share.porwolik.com/ftp/perun/Perun.htm)
* 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
* click connect and leave the app running in the background
* 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
* by default the UDP port 48620 is in use as target port
## Data packets
* ID: 1, contains version information
* ID: 2, contains status data in the following sections
* mission
* players
* mission - minimal information
* players - connected players
* ID: 3, available slots list and coalitions
* coalitions
* slots
* coalitions - available coalitions
* slots - available slots
* ID: 4, stores mission data **ONLY JSON FILE**
* ID: 50, chat event
* ID: 51, game event
* 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