From f309d49d4a619973fc1bbb475cdaf637e595e1f4 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Thu, 5 Dec 2019 23:54:52 +0100 Subject: [PATCH 01/29] start merge to dotnetcore --- Lora-Bot/Lora-Bot_Core.csproj | 53 ++++++++++++++ Lora-Bot/Properties/AssemblyInfo.cs | 6 +- Lora-Bot_Core.sln | 103 ++++++++++++++++++++++++++++ 3 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 Lora-Bot/Lora-Bot_Core.csproj create mode 100644 Lora-Bot_Core.sln diff --git a/Lora-Bot/Lora-Bot_Core.csproj b/Lora-Bot/Lora-Bot_Core.csproj new file mode 100644 index 0000000..25d86f0 --- /dev/null +++ b/Lora-Bot/Lora-Bot_Core.csproj @@ -0,0 +1,53 @@ + + + + Exe + netcoreapp3.0 + Fraunhofer.Fit.IoT.Bots.LoraBot + Lora-Bot + Program that runs on a device and process the Lora traffic from the Lora library + Fraunhofer FIT + BlubbFish + 1.8.4 + Copyright © BlubbFish 2018 - 08.07.2019 + LICENSE + de-DE + https://github.com/MONICA-Project/lora-bot + https://github.com/MONICA-Project/lora-bot.git + git + 1.8.4 Fixing a bug related to threaded working with data +1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend +1.8.2 Bugfix, create also an event for sending normal loradata when update panic +1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved +1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC +1.7.3 Parsing new Status format and Panic Package +1.7.2 Update to local librarys +1.7.1 Fixing binary data transmission & fixing Scral Plugin +1.7.0 Adding IC800A Lora-Reciever +1.6.2 Adding a test for LoraBinary +1.6.1 Fixing parsing bug with linebreaks in Lora +1.6.0 Implement Height in LoraBot +1.5.1 Dependencies in debian Packet cleaned +1.5.0 Send over Mqtt the new status items and refactoring +1.4.1 Remove old Wirelesscode and Rename some Classes +1.4.0 Adding Debugmode for finetuning Lora-Trackers +1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value +1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile +1.1.0 Update Scral addresses + + + + + + + + + + + + True + + + + + diff --git a/Lora-Bot/Properties/AssemblyInfo.cs b/Lora-Bot/Properties/AssemblyInfo.cs index 13d1739..e005e28 100644 --- a/Lora-Bot/Properties/AssemblyInfo.cs +++ b/Lora-Bot/Properties/AssemblyInfo.cs @@ -1,4 +1,5 @@ -using System.Reflection; +#if !NETCOREAPP +using System.Reflection; using System.Resources; using System.Runtime.InteropServices; @@ -10,7 +11,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Fraunhofer FIT")] [assembly: AssemblyProduct("Lora-Bot")] -[assembly: AssemblyCopyright("Copyright © 2018 - 08.07.2019")] +[assembly: AssemblyCopyright("Copyright © BlubbFish 2018 - 08.07.2019")] [assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")] [assembly: AssemblyCulture("")] [assembly: NeutralResourcesLanguage("de-DE")] @@ -35,6 +36,7 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.8.4")] [assembly: AssemblyFileVersion("1.8.4")] +#endif /* * 1.1.0 Update Scral addresses * 1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile diff --git a/Lora-Bot_Core.sln b/Lora-Bot_Core.sln new file mode 100644 index 0000000..13bb56d --- /dev/null +++ b/Lora-Bot_Core.sln @@ -0,0 +1,103 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.87 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora-Bot_Core", "Lora-Bot\Lora-Bot_Core.csproj", "{A5D551AD-ADBC-425C-B314-89D04E2DED62}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora_Core", "..\Lora\Lora\Lora_Core.csproj", "{A3B254DD-9B58-4A95-9659-CB41AFBA9435}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Iot-Interfaces_Core", "..\Utils\Iot-Interfaces\Iot-Interfaces\Iot-Interfaces_Core.csproj", "{84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils_Core", "..\Utils\Utils\Utils\Utils_Core.csproj", "{C094C744-3F47-494F-A835-3FE5C1AD9A26}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson_Core", "..\Librarys\litjson\litjson\litjson_Core.csproj", "{75ED402F-92D6-43DA-B7DE-FBB65E8A327A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan", "..\Librarys\RaspberryIO_26\Swan\Swan.csproj", "{A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan.Lite", "..\Librarys\RaspberryIO_26\Swan.Lite\Swan.Lite.csproj", "{CBD456D3-D3E3-4197-998C-B2F8CDD4F822}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{C9C54488-2712-47BC-AACD-1BAD4551C15D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO.Abstractions", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO.Abstractions\Unosquare.RaspberryIO.Abstractions.csproj", "{DE99DB1B-6E32-4F04-94CD-F210647302EB}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{5B05D050-96EC-447C-9780-4078511B3C7F}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt_Core", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj", "{2711D97D-9371-47CF-97CB-D4A74F4A7193}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt_Core", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj", "{3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT_Core", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT_Core.csproj", "{C4CE902A-8BBC-45A4-8074-9448DF5469DE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils_Core", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj", "{3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.Build.0 = Release|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.Build.0 = Release|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.Build.0 = Release|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.Build.0 = Release|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.Build.0 = Release|Any CPU + {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Release|Any CPU.Build.0 = Release|Any CPU + {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Release|Any CPU.Build.0 = Release|Any CPU + {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Release|Any CPU.Build.0 = Release|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.Build.0 = Release|Any CPU + {5B05D050-96EC-447C-9780-4078511B3C7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5B05D050-96EC-447C-9780-4078511B3C7F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5B05D050-96EC-447C-9780-4078511B3C7F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5B05D050-96EC-447C-9780-4078511B3C7F}.Release|Any CPU.Build.0 = Release|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.Build.0 = Release|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.Build.0 = Release|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.Build.0 = Release|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5F8C5805-2E23-426D-9921-92DFA67B58F3} + EndGlobalSection +EndGlobal From 9ad0669becc28b133e24a1750e800fbbfa2080db Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Tue, 10 Dec 2019 21:46:23 +0100 Subject: [PATCH 02/29] Change references --- Lora-Bot/Lora-Bot_Core.csproj | 6 +++++ Lora-Bot_Core.sln | 42 +++++++++++++++-------------------- README.md | 9 ++++++++ 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/Lora-Bot/Lora-Bot_Core.csproj b/Lora-Bot/Lora-Bot_Core.csproj index 25d86f0..33d67a6 100644 --- a/Lora-Bot/Lora-Bot_Core.csproj +++ b/Lora-Bot/Lora-Bot_Core.csproj @@ -43,6 +43,12 @@ + + + + + + True diff --git a/Lora-Bot_Core.sln b/Lora-Bot_Core.sln index 13bb56d..1afae05 100644 --- a/Lora-Bot_Core.sln +++ b/Lora-Bot_Core.sln @@ -13,16 +13,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils_Core", "..\Utils\Util EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson_Core", "..\Librarys\litjson\litjson\litjson_Core.csproj", "{75ED402F-92D6-43DA-B7DE-FBB65E8A327A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan", "..\Librarys\RaspberryIO_26\Swan\Swan.csproj", "{A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan.Lite", "..\Librarys\RaspberryIO_26\Swan.Lite\Swan.Lite.csproj", "{CBD456D3-D3E3-4197-998C-B2F8CDD4F822}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{C9C54488-2712-47BC-AACD-1BAD4551C15D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO.Abstractions", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO.Abstractions\Unosquare.RaspberryIO.Abstractions.csproj", "{DE99DB1B-6E32-4F04-94CD-F210647302EB}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{5B05D050-96EC-447C-9780-4078511B3C7F}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt_Core", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj", "{2711D97D-9371-47CF-97CB-D4A74F4A7193}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt_Core", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj", "{3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}" @@ -31,6 +23,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT_Core", "..\Utils\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils_Core", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj", "{3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan.Tiny", "..\Librarys\RaspberryIO_26\Swan.Tiny\Swan.Tiny.csproj", "{0842C808-DF6D-41A1-8A90-2FF9C14F2148}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{11BAD50E-CA85-4FC9-96D3-8B60778BB091}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{037664CC-0F00-4DFE-AD5F-19AF2DE3431F}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -57,26 +55,10 @@ Global {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.Build.0 = Debug|Any CPU {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.ActiveCfg = Release|Any CPU {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.Build.0 = Release|Any CPU - {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3E6FFF4-751E-4F1D-A7B3-AB06A7381E51}.Release|Any CPU.Build.0 = Release|Any CPU - {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CBD456D3-D3E3-4197-998C-B2F8CDD4F822}.Release|Any CPU.Build.0 = Release|Any CPU - {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C9C54488-2712-47BC-AACD-1BAD4551C15D}.Release|Any CPU.Build.0 = Release|Any CPU {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.Build.0 = Debug|Any CPU {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.ActiveCfg = Release|Any CPU {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.Build.0 = Release|Any CPU - {5B05D050-96EC-447C-9780-4078511B3C7F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5B05D050-96EC-447C-9780-4078511B3C7F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5B05D050-96EC-447C-9780-4078511B3C7F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5B05D050-96EC-447C-9780-4078511B3C7F}.Release|Any CPU.Build.0 = Release|Any CPU {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.Build.0 = Debug|Any CPU {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -93,6 +75,18 @@ Global {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.Build.0 = Release|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.Build.0 = Release|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.Build.0 = Release|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/README.md b/README.md index daa49c3..451183f 100644 --- a/README.md +++ b/README.md @@ -44,6 +44,15 @@ The only way to test this programm is to run it on real hardware. Please build it with Visual Studio. +To install dotnet on a Raspi: +* [Download .NET Core Runtime 3.1.0](https://dotnet.microsoft.com/download/dotnet-core/3.1) for ARM32 +```bash +wget [download link] +sudo mkdir /usr/share/dotnet +export PATH=$PATH:/usr/share/dotnet/ +sudo tar zxf dotnet-runtime-3.1.0-linux-arm.tar.gz -C /usr/share/dotnet +``` + ## Contributing Contributions are welcome. From d029c62d5b35308d311ec06c76bb58a9c894e6e4 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Wed, 11 Dec 2019 15:31:15 +0100 Subject: [PATCH 03/29] change refs --- .github/workflows/dotnetcore.yml | 113 ++++++++++++++++++++++ Lora-Bot.sln | 136 +++++++++++++------------- Lora-Bot/Lora-Bot.csproj | 143 ++++++++++------------------ Lora-Bot/Lora-Bot.csproj.user | 6 -- Lora-Bot/Lora-Bot_Core.csproj | 59 ------------ Lora-Bot/Properties/AssemblyInfo.cs | 60 ------------ Lora-Bot/gpio.2.44 | Bin 37076 -> 0 bytes Lora-Bot/libwiringPi.so.2.44 | Bin 69852 -> 0 bytes Lora-Bot_Core.sln | 97 ------------------- README.md | 4 + 10 files changed, 235 insertions(+), 383 deletions(-) create mode 100644 .github/workflows/dotnetcore.yml delete mode 100644 Lora-Bot/Lora-Bot.csproj.user delete mode 100644 Lora-Bot/Lora-Bot_Core.csproj delete mode 100644 Lora-Bot/Properties/AssemblyInfo.cs delete mode 100644 Lora-Bot/gpio.2.44 delete mode 100644 Lora-Bot/libwiringPi.so.2.44 delete mode 100644 Lora-Bot_Core.sln diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml new file mode 100644 index 0000000..88c9d7c --- /dev/null +++ b/.github/workflows/dotnetcore.yml @@ -0,0 +1,113 @@ +name: Build, Test, Publish and Dockerise TTN-Bridge +FAIL! +on: [push] + +jobs: + build: + name: Build, pack and release + runs-on: ubuntu-latest + steps: + - name: Checkout parent project with dependencys + uses: actions/checkout@v1 + with: + repository: MONICA-Project/ttn-bridge-project + ref: refs/heads/master + submodules: true + + - name: Checkout last versions + run: git -C TTN-Bridge checkout --progress --force ${{ github.sha }} + working-directory: ../ttn-bridge-project + + - name: Install dotnet + uses: actions/setup-dotnet@v1 + with: + dotnet-version: 3.0.100 + + - name: Build with dotnet + run: dotnet build TTN-Bridge.sln --configuration Release + working-directory: ../ttn-bridge-project/TTN-Bridge + + - name: Create deb files + if: success() + run: | + mkdir ../../../Builds + chmod oug+x make-deb.sh + ./make-deb.sh amd64 + ./make-deb.sh armhf + id: create_deb + working-directory: ../ttn-bridge-project/TTN-Bridge/TTN-Bridge/dpkg + + - name: Create release + if: success() + id: nightly_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ steps.create_deb.outputs.builddaterelease }} + release_name: Nightly from master + body: This is a nightly release. It may be not working properly. + draft: false + prerelease: true + + - name: Upload release asset amd64 + if: success() + id: upload-release-asset-amd64 + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.nightly_release.outputs.upload_url }} + asset_path: ../ttn-bridge-project/Builds/amd64-${{ steps.create_deb.outputs.debuilderfile }} + asset_name: amd64-${{ steps.create_deb.outputs.debuilderfile }} + asset_content_type: application/x-deb + + - name: Upload release asset armhf + if: success() + id: upload-release-asset-armhf + uses: actions/upload-release-asset@v1.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ steps.nightly_release.outputs.upload_url }} + asset_path: ../ttn-bridge-project/Builds/armhf-${{ steps.create_deb.outputs.debuilderfile }} + asset_name: armhf-${{ steps.create_deb.outputs.debuilderfile }} + asset_content_type: application/x-deb + + docker: + name: Build and push dockerfile + runs-on: ubuntu-latest + steps: + - name: Checkout parent project with dependencys + uses: actions/checkout@v1 + with: + repository: MONICA-Project/ttn-bridge-project + ref: refs/heads/master + submodules: true + + - name: Checkout last versions + run: git -C TTN-Bridge checkout --progress --force ${{ github.sha }} + working-directory: ../ttn-bridge-project + + - name: Docker build + id: docker_build + run: | + DOCKERTAG=$(date +%Y%m%d%H%M%S) + echo "##[set-output name=dockertag;]$DOCKERTAG" + docker build . -t monicaproject/ttn-bridge:latest -t monicaproject/ttn-bridge:$DOCKERTAG + working-directory: ../ttn-bridge-project + + - name: Docker-compose publish + if: success() + run: | + echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin ${INPUT_REGISTRY} + docker push monicaproject/ttn-bridge:latest + docker push monicaproject/ttn-bridge:${{ steps.docker_build.outputs.dockertag }} + working-directory: ../ttn-bridge-project + +# VMAJOR=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 1) +# VMINOR=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 2) +# VBUILD=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 3) +# TARGETFILE="ttnbridge_$VMAJOR.$VMINOR-$VBUILD.deb" +# echo "##[set-output name=debuilderfile;]$TARGETFILE" +# echo "##[set-output name=builddaterelease;]$(date +"%F_%H%M%S")" \ No newline at end of file diff --git a/Lora-Bot.sln b/Lora-Bot.sln index f5cd722..f48f9a3 100644 --- a/Lora-Bot.sln +++ b/Lora-Bot.sln @@ -1,33 +1,33 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27703.2026 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29519.87 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lora-Bot", "Lora-Bot\Lora-Bot.csproj", "{FB11B997-AF4D-427F-96FD-4C84143057CF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora-Bot", "Lora-Bot\Lora-Bot.csproj", "{A5D551AD-ADBC-425C-B314-89D04E2DED62}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lora", "..\Lora\Lora\Lora.csproj", "{85A78B05-5843-4E4D-8C56-4BCB12613750}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora", "..\Lora\Lora\Lora.csproj", "{A3B254DD-9B58-4A95-9659-CB41AFBA9435}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Iot-Interfaces", "..\Utils\Iot-Interfaces\Iot-Interfaces\Iot-Interfaces.csproj", "{4DAADA29-C600-4CF3-8AD3-9C97C8D7F632}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Iot-Interfaces_Core", "..\Utils\Iot-Interfaces\Iot-Interfaces\Iot-Interfaces_Core.csproj", "{84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "litjson_4.7.1", "..\Librarys\litjson\litjson\litjson_4.7.1.csproj", "{91A14CD2-2940-4500-8193-56D37EDDDBAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils_Core", "..\Utils\Utils\Utils\Utils_Core.csproj", "{C094C744-3F47-494F-A835-3FE5C1AD9A26}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bot-Utils", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils.csproj", "{BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson_Core", "..\Librarys\litjson\litjson\litjson_Core.csproj", "{75ED402F-92D6-43DA-B7DE-FBB65E8A327A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO.Abstractions", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO.Abstractions\Unosquare.RaspberryIO.Abstractions.csproj", "{DE99DB1B-6E32-4F04-94CD-F210647302EB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConnectorDataMqtt", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt.csproj", "{EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt_Core", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj", "{2711D97D-9371-47CF-97CB-D4A74F4A7193}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils-IoT", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT.csproj", "{B870E4D5-6806-4A0B-B233-8907EEDC5AFC}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt_Core", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj", "{3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt_4.7.1", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_4.7.1.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT_Core", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT_Core.csproj", "{C4CE902A-8BBC-45A4-8074-9448DF5469DE}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Posix", "..\Librarys\Mono.Posix\Mono.Posix\Mono.Posix.csproj", "{E2CA132E-E85C-40AD-BE94-B138AA68772B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils_Core", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj", "{3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Swan.Lite", "..\Librarys\RaspberryIO\Unosquare.Swan.Lite\Unosquare.Swan.Lite.csproj", "{AB015683-62E5-47F1-861F-6D037F9C6433}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan.Tiny", "..\Librarys\RaspberryIO_26\Swan.Tiny\Swan.Tiny.csproj", "{0842C808-DF6D-41A1-8A90-2FF9C14F2148}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.Swan", "..\Librarys\RaspberryIO\Unosquare.Swan\Unosquare.Swan.csproj", "{2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{11BAD50E-CA85-4FC9-96D3-8B60778BB091}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{8C5D4DE9-377F-4EC8-873D-6EEF15F43516}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{037664CC-0F00-4DFE-AD5F-19AF2DE3431F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -35,63 +35,63 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {FB11B997-AF4D-427F-96FD-4C84143057CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB11B997-AF4D-427F-96FD-4C84143057CF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FB11B997-AF4D-427F-96FD-4C84143057CF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB11B997-AF4D-427F-96FD-4C84143057CF}.Release|Any CPU.Build.0 = Release|Any CPU - {85A78B05-5843-4E4D-8C56-4BCB12613750}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {85A78B05-5843-4E4D-8C56-4BCB12613750}.Debug|Any CPU.Build.0 = Debug|Any CPU - {85A78B05-5843-4E4D-8C56-4BCB12613750}.Release|Any CPU.ActiveCfg = Release|Any CPU - {85A78B05-5843-4E4D-8C56-4BCB12613750}.Release|Any CPU.Build.0 = Release|Any CPU - {4DAADA29-C600-4CF3-8AD3-9C97C8D7F632}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4DAADA29-C600-4CF3-8AD3-9C97C8D7F632}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4DAADA29-C600-4CF3-8AD3-9C97C8D7F632}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4DAADA29-C600-4CF3-8AD3-9C97C8D7F632}.Release|Any CPU.Build.0 = Release|Any CPU - {91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {91A14CD2-2940-4500-8193-56D37EDDDBAA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {91A14CD2-2940-4500-8193-56D37EDDDBAA}.Release|Any CPU.Build.0 = Release|Any CPU - {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BB7BFCB5-3DB0-49E1-802A-3CE3EECC59F9}.Release|Any CPU.Build.0 = Release|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|Any CPU.Build.0 = Release|Any CPU - {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE6C8F68-ED46-4C1C-ABDD-CFCDF75104F2}.Release|Any CPU.Build.0 = Release|Any CPU - {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B870E4D5-6806-4A0B-B233-8907EEDC5AFC}.Release|Any CPU.Build.0 = Release|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU - {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E2CA132E-E85C-40AD-BE94-B138AA68772B}.Release|Any CPU.Build.0 = Release|Any CPU - {AB015683-62E5-47F1-861F-6D037F9C6433}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB015683-62E5-47F1-861F-6D037F9C6433}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB015683-62E5-47F1-861F-6D037F9C6433}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB015683-62E5-47F1-861F-6D037F9C6433}.Release|Any CPU.Build.0 = Release|Any CPU - {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2EA5E3E4-F8C8-4742-8C78-4B070AFCFB73}.Release|Any CPU.Build.0 = Release|Any CPU - {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8C5D4DE9-377F-4EC8-873D-6EEF15F43516}.Release|Any CPU.Build.0 = Release|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.Build.0 = Release|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.Build.0 = Release|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.Build.0 = Release|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.Build.0 = Release|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.Build.0 = Release|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.Build.0 = Release|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.Build.0 = Release|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.Build.0 = Release|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.Build.0 = Release|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.Build.0 = Release|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.Build.0 = Release|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.Build.0 = Debug|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.ActiveCfg = Release|Any CPU + {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.Build.0 = Release|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {82B8A2F0-7ECF-4377-B7C6-71FB9EEC1102} + SolutionGuid = {5F8C5805-2E23-426D-9921-92DFA67B58F3} EndGlobalSection EndGlobal diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index 3bb8534..50e7e5b 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -1,105 +1,62 @@ - - - + + - Debug - AnyCPU - {FB11B997-AF4D-427F-96FD-4C84143057CF} Exe + netcoreapp3.0 Fraunhofer.Fit.IoT.Bots.LoraBot Lora-Bot - v4.7.1 - 512 - true + Program that runs on a device and process the Lora traffic from the Lora library + Fraunhofer FIT + BlubbFish + 1.8.4 + Copyright © Fraunhofer FIT, BlubbFish 2018 - 08.07.2019 + LICENSE + de-DE + https://github.com/MONICA-Project/lora-bot + https://github.com/MONICA-Project/lora-bot.git + git + 1.8.4 Fixing a bug related to threaded working with data +1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend +1.8.2 Bugfix, create also an event for sending normal loradata when update panic +1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved +1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC +1.7.3 Parsing new Status format and Panic Package +1.7.2 Update to local librarys +1.7.1 Fixing binary data transmission & fixing Scral Plugin +1.7.0 Adding IC800A Lora-Reciever +1.6.2 Adding a test for LoraBinary +1.6.1 Fixing parsing bug with linebreaks in Lora +1.6.0 Implement Height in LoraBot +1.5.1 Dependencies in debian Packet cleaned +1.5.0 Send over Mqtt the new status items and refactoring +1.4.1 Remove old Wirelesscode and Rename some Classes +1.4.0 Adding Debugmode for finetuning Lora-Trackers +1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value +1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile +1.1.0 Update Scral addresses + Fraunhofer.Fit.IoT.Bots.LoraBot.Program + LoraBot.Bots.IoT.Fit.Fraunhofer - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - + - - - - + + + + + - - {ee6c8f68-ed46-4c1c-abdd-cfcdf75104f2} - ConnectorDataMqtt - - - {b870e4d5-6806-4a0b-b233-8907eedc5afc} - Utils-IoT - - - {fac8ce64-bf13-4ece-8097-aeb5dd060098} - Utils - - - {91a14cd2-2940-4500-8193-56d37edddbaa} - litjson_4.7.1 - - - {85a78b05-5843-4e4d-8c56-4bcb12613750} - Lora - - - {bb7bfcb5-3db0-49e1-802a-3ce3eecc59f9} - Bot-Utils - - - {4daada29-c600-4cf3-8ad3-9c97c8d7f632} - Iot-Interfaces - + + + + + - - PreserveNewest - - - PreserveNewest - - - PreserveNewest + + True + - - - - - - - - - - - - - - \ No newline at end of file + + diff --git a/Lora-Bot/Lora-Bot.csproj.user b/Lora-Bot/Lora-Bot.csproj.user deleted file mode 100644 index b6809fe..0000000 --- a/Lora-Bot/Lora-Bot.csproj.user +++ /dev/null @@ -1,6 +0,0 @@ - - - - -freq 868100000 -sp 8 -bw 62500 -cr 6 - - \ No newline at end of file diff --git a/Lora-Bot/Lora-Bot_Core.csproj b/Lora-Bot/Lora-Bot_Core.csproj deleted file mode 100644 index 33d67a6..0000000 --- a/Lora-Bot/Lora-Bot_Core.csproj +++ /dev/null @@ -1,59 +0,0 @@ - - - - Exe - netcoreapp3.0 - Fraunhofer.Fit.IoT.Bots.LoraBot - Lora-Bot - Program that runs on a device and process the Lora traffic from the Lora library - Fraunhofer FIT - BlubbFish - 1.8.4 - Copyright © BlubbFish 2018 - 08.07.2019 - LICENSE - de-DE - https://github.com/MONICA-Project/lora-bot - https://github.com/MONICA-Project/lora-bot.git - git - 1.8.4 Fixing a bug related to threaded working with data -1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend -1.8.2 Bugfix, create also an event for sending normal loradata when update panic -1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved -1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC -1.7.3 Parsing new Status format and Panic Package -1.7.2 Update to local librarys -1.7.1 Fixing binary data transmission & fixing Scral Plugin -1.7.0 Adding IC800A Lora-Reciever -1.6.2 Adding a test for LoraBinary -1.6.1 Fixing parsing bug with linebreaks in Lora -1.6.0 Implement Height in LoraBot -1.5.1 Dependencies in debian Packet cleaned -1.5.0 Send over Mqtt the new status items and refactoring -1.4.1 Remove old Wirelesscode and Rename some Classes -1.4.0 Adding Debugmode for finetuning Lora-Trackers -1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value -1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile -1.1.0 Update Scral addresses - - - - - - - - - - - - - - - - - - True - - - - - diff --git a/Lora-Bot/Properties/AssemblyInfo.cs b/Lora-Bot/Properties/AssemblyInfo.cs deleted file mode 100644 index e005e28..0000000 --- a/Lora-Bot/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,60 +0,0 @@ -#if !NETCOREAPP -using System.Reflection; -using System.Resources; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die einer Assembly zugeordnet sind. -[assembly: AssemblyTitle("Lora-Bot")] -[assembly: AssemblyDescription("Program that runs on a device and process the Lora traffic from the Lora library")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Fraunhofer FIT")] -[assembly: AssemblyProduct("Lora-Bot")] -[assembly: AssemblyCopyright("Copyright © BlubbFish 2018 - 08.07.2019")] -[assembly: AssemblyTrademark("Fraunhofer FIT, BlubbFish")] -[assembly: AssemblyCulture("")] -[assembly: NeutralResourcesLanguage("de-DE")] - -// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly -// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von -// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("fb11b997-af4d-427f-96fd-4c84143057cf")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.8.4")] -[assembly: AssemblyFileVersion("1.8.4")] -#endif -/* - * 1.1.0 Update Scral addresses - * 1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile - * 1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value - * 1.4.0 Adding Debugmode for finetuning Lora-Trackers - * 1.4.1 Remove old Wirelesscode and Rename some Classes - * 1.5.0 Send over Mqtt the new status items and refactoring - * 1.5.1 Dependencies in debian Packet cleaned - * 1.6.0 Implement Height in LoraBot - * 1.6.1 Fixing parsing bug with linebreaks in Lora - * 1.6.2 Adding a test for LoraBinary - * 1.7.0 Adding IC800A Lora-Reciever - * 1.7.1 Fixing binary data transmission & fixing Scral Plugin - * 1.7.2 Update to local librarys - * 1.7.3 Parsing new Status format and Panic Package - * 1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC - * 1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved - * 1.8.2 Bugfix, create also an event for sending normal loradata when update panic - * 1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend - * 1.8.4 Fixing a bug related to threaded working with data - */ diff --git a/Lora-Bot/gpio.2.44 b/Lora-Bot/gpio.2.44 deleted file mode 100644 index 573c114117f358fc94c4f94094cc765364004065..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 37076 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

lwu;bp94LKWzCx)ED0(>}dS$|gfC{moh+T*_` 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 H4CwuTN*+^4 diff --git a/Lora-Bot/libwiringPi.so.2.44 b/Lora-Bot/libwiringPi.so.2.44 deleted file mode 100644 index d7c3ba549248e49a9121eb1c0347d50246630f38..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 69852 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 Vaq{@8N%B3`+N6H!3L$lT{{xu49~}Sy diff --git a/Lora-Bot_Core.sln b/Lora-Bot_Core.sln deleted file mode 100644 index 1afae05..0000000 --- a/Lora-Bot_Core.sln +++ /dev/null @@ -1,97 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.29519.87 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora-Bot_Core", "Lora-Bot\Lora-Bot_Core.csproj", "{A5D551AD-ADBC-425C-B314-89D04E2DED62}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Lora_Core", "..\Lora\Lora\Lora_Core.csproj", "{A3B254DD-9B58-4A95-9659-CB41AFBA9435}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Iot-Interfaces_Core", "..\Utils\Iot-Interfaces\Iot-Interfaces\Iot-Interfaces_Core.csproj", "{84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils_Core", "..\Utils\Utils\Utils\Utils_Core.csproj", "{C094C744-3F47-494F-A835-3FE5C1AD9A26}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "litjson_Core", "..\Librarys\litjson\litjson\litjson_Core.csproj", "{75ED402F-92D6-43DA-B7DE-FBB65E8A327A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO.Abstractions", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO.Abstractions\Unosquare.RaspberryIO.Abstractions.csproj", "{DE99DB1B-6E32-4F04-94CD-F210647302EB}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConnectorDataMqtt_Core", "..\Utils\ConnectorDataMqtt\ConnectorDataMqtt\ConnectorDataMqtt_Core.csproj", "{2711D97D-9371-47CF-97CB-D4A74F4A7193}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "M2Mqtt_Core", "..\Librarys\mqtt\M2Mqtt\M2Mqtt_Core.csproj", "{3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Utils-IoT_Core", "..\Utils\Utils-IoT\Utils-IoT\Utils-IoT_Core.csproj", "{C4CE902A-8BBC-45A4-8074-9448DF5469DE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bot-Utils_Core", "..\Utils\Bot-Utils\Bot-Utils\Bot-Utils_Core.csproj", "{3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Swan.Tiny", "..\Librarys\RaspberryIO_26\Swan.Tiny\Swan.Tiny.csproj", "{0842C808-DF6D-41A1-8A90-2FF9C14F2148}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", "..\Librarys\RaspberryIO_26\Unosquare.RaspberryIO\Unosquare.RaspberryIO.csproj", "{11BAD50E-CA85-4FC9-96D3-8B60778BB091}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{037664CC-0F00-4DFE-AD5F-19AF2DE3431F}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A5D551AD-ADBC-425C-B314-89D04E2DED62}.Release|Any CPU.Build.0 = Release|Any CPU - {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3B254DD-9B58-4A95-9659-CB41AFBA9435}.Release|Any CPU.Build.0 = Release|Any CPU - {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {84DB81BD-26EB-42B4-91E1-F8C4FF6DD2E5}.Release|Any CPU.Build.0 = Release|Any CPU - {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C094C744-3F47-494F-A835-3FE5C1AD9A26}.Release|Any CPU.Build.0 = Release|Any CPU - {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {75ED402F-92D6-43DA-B7DE-FBB65E8A327A}.Release|Any CPU.Build.0 = Release|Any CPU - {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DE99DB1B-6E32-4F04-94CD-F210647302EB}.Release|Any CPU.Build.0 = Release|Any CPU - {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2711D97D-9371-47CF-97CB-D4A74F4A7193}.Release|Any CPU.Build.0 = Release|Any CPU - {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3E8500D2-A9E6-4A85-9A95-E6C8AFF6298B}.Release|Any CPU.Build.0 = Release|Any CPU - {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4CE902A-8BBC-45A4-8074-9448DF5469DE}.Release|Any CPU.Build.0 = Release|Any CPU - {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3D449CEF-CF03-4D3B-A531-4B2DD7B52E88}.Release|Any CPU.Build.0 = Release|Any CPU - {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0842C808-DF6D-41A1-8A90-2FF9C14F2148}.Release|Any CPU.Build.0 = Release|Any CPU - {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Debug|Any CPU.Build.0 = Debug|Any CPU - {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.ActiveCfg = Release|Any CPU - {11BAD50E-CA85-4FC9-96D3-8B60778BB091}.Release|Any CPU.Build.0 = Release|Any CPU - {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {037664CC-0F00-4DFE-AD5F-19AF2DE3431F}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {5F8C5805-2E23-426D-9921-92DFA67B58F3} - EndGlobalSection -EndGlobal diff --git a/README.md b/README.md index 451183f..f7e6c9b 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,10 @@ This projects depends on some librarys: #### External * litjson +* M2Mqtt +* Unosquare Swan +* Unosquare RaspberryIO +* Unosquare WiringPI ### Test From 210ed7817dacef7a6a1709465599c3c32d8141e2 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Mon, 16 Dec 2019 14:43:47 +0100 Subject: [PATCH 04/29] Remove CMD Args and make debugging easyer --- Lora-Bot/Program.cs | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/Lora-Bot/Program.cs b/Lora-Bot/Program.cs index 921db1d..67934e5 100644 --- a/Lora-Bot/Program.cs +++ b/Lora-Bot/Program.cs @@ -8,21 +8,18 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot { class Program : Bot { static void Main(String[] args) => new Program(args); - public Program(String[] args) { + public Program(String[] _) { InIReader.SetSearchPath(new List() { "/etc/lorabot", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\lorabot" }); - CmdArgs.Instance.SetArguments(new Dictionary() { - { "-freq", new CmdArgs.VaildArguments(CmdArgs.ArgLength.Touple) }, - { "-bw", new CmdArgs.VaildArguments(CmdArgs.ArgLength.Touple) }, - { "-sp", new CmdArgs.VaildArguments(CmdArgs.ArgLength.Touple) }, - { "-cr", new CmdArgs.VaildArguments(CmdArgs.ArgLength.Touple) }, - }, args); - if (!CmdArgs.Instance.HasArgumentType("-freq") && !CmdArgs.Instance.HasArgumentType("-bw") && !CmdArgs.Instance.HasArgumentType("-sp") && !CmdArgs.Instance.HasArgumentType("-cr")) { - if (!InIReader.ConfigExist("settings")) { - Helper.WriteError("No settings.ini found. Abord!"); - return; - } - InIReader settings = InIReader.GetInstance("settings"); - this.logger.SetPath(settings.GetValue("logging", "path")); + if (!InIReader.ConfigExist("settings")) { + Helper.WriteError("No settings.ini found. Abord!"); + return; + } + InIReader settings = InIReader.GetInstance("settings"); + this.logger.SetPath(settings.GetValue("logging", "path")); + if (settings.GetValue("lora","debug") == "true") { + LoraController lora = new LoraController(settings.GetSection("lora"), false); + lora.Dispose(); + } else { LoraController lora = new LoraController(settings.GetSection("lora")); this.ModulLoader("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls", lora); this.ModulInterconnect(); @@ -36,15 +33,6 @@ public Program(String[] args) { Console.WriteLine("after dispose"); lora.Dispose(); Console.WriteLine("after loradisp"); - } else if(CmdArgs.Instance.HasArgumentType("-freq") && CmdArgs.Instance.HasArgumentType("-bw") && CmdArgs.Instance.HasArgumentType("-sp") && CmdArgs.Instance.HasArgumentType("-cr")) { - LoraController lora = new LoraController(new Dictionary() { - { "frequency", CmdArgs.Instance.GetArgumentData("-freq") }, - { "signalbandwith", CmdArgs.Instance.GetArgumentData("-bw") }, - { "spreadingfactor", CmdArgs.Instance.GetArgumentData("-sp") }, - { "codingrate", CmdArgs.Instance.GetArgumentData("-cr") } - }, false); - } else { - Helper.WriteError("Usage for Debug:\n" + CmdArgs.Instance.GetUsageList("Lora-Bot")); } } From 13b6a26b5a84759a27113416d3ca4f34e945d3fc Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Fri, 20 Dec 2019 00:20:37 +0100 Subject: [PATCH 05/29] Moved a lot stuff from Lora to Lora-Bot --- Lora-Bot/Events/DataUpdateEvent.cs | 17 ++ Lora-Bot/Events/GpsUpdateEvent.cs | 49 ++++ Lora-Bot/Events/PanicUpdateEvent.cs | 17 ++ Lora-Bot/Events/StatusUpdateEvent.cs | 40 +++ Lora-Bot/Events/TrackerUpdateEvent.cs | 86 ++++++ Lora-Bot/Events/UpdateEventHelper.cs | 41 +++ Lora-Bot/Models/GpsInfo.cs | 88 ++++++ Lora-Bot/Models/Tracker.cs | 259 ++++++++++++++++++ Lora-Bot/Moduls/Mqtt.cs | 4 +- Lora-Bot/Moduls/Txtout.cs | 4 +- Lora-Bot/Parser/LoraParser.cs | 20 ++ Lora-Bot/Program.cs | 50 ++-- Lora-Bot/config-example/settings.conf.example | 26 +- README.md | 3 +- 14 files changed, 667 insertions(+), 37 deletions(-) create mode 100644 Lora-Bot/Events/DataUpdateEvent.cs create mode 100644 Lora-Bot/Events/GpsUpdateEvent.cs create mode 100644 Lora-Bot/Events/PanicUpdateEvent.cs create mode 100644 Lora-Bot/Events/StatusUpdateEvent.cs create mode 100644 Lora-Bot/Events/TrackerUpdateEvent.cs create mode 100644 Lora-Bot/Events/UpdateEventHelper.cs create mode 100644 Lora-Bot/Models/GpsInfo.cs create mode 100644 Lora-Bot/Models/Tracker.cs create mode 100644 Lora-Bot/Parser/LoraParser.cs diff --git a/Lora-Bot/Events/DataUpdateEvent.cs b/Lora-Bot/Events/DataUpdateEvent.cs new file mode 100644 index 0000000..ad0d97e --- /dev/null +++ b/Lora-Bot/Events/DataUpdateEvent.cs @@ -0,0 +1,17 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class DataUpdateEvent : TrackerUpdateEvent { + public GpsUpdateEvent Gps { + get; private set; + } + + public DataUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); + + public override String MqttTopic() => "data/" + base.MqttTopic(); + + public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); + } +} diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs new file mode 100644 index 0000000..ef8fae0 --- /dev/null +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -0,0 +1,49 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class GpsUpdateEvent : UpdateEventHelper { + public Boolean Fix { + get; private set; + } + public Double Hdop { + get; private set; + } + public Double Height { + get; private set; + } + public Double Latitude { + get; private set; + } + public Double Longitude { + get; private set; + } + public Double LastLatitude { + get; private set; + } + public Double LastLongitude { + get; private set; + } + public DateTime LastGPSPos { + get; private set; + } + public DateTime Time { + get; private set; + } + + public GpsUpdateEvent(GpsInfo gps) { + this.Fix = gps.Fix; + this.Hdop = gps.Hdop; + this.Height = gps.Height; + this.Latitude = gps.Latitude; + this.Longitude = gps.Longitude; + this.Time = gps.Time; + this.LastLatitude = gps.LastLatitude; + this.LastLongitude = gps.LastLongitude; + this.LastGPSPos = gps.LastGPSPos; + } + + public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; + } +} diff --git a/Lora-Bot/Events/PanicUpdateEvent.cs b/Lora-Bot/Events/PanicUpdateEvent.cs new file mode 100644 index 0000000..5f13453 --- /dev/null +++ b/Lora-Bot/Events/PanicUpdateEvent.cs @@ -0,0 +1,17 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class PanicUpdateEvent : TrackerUpdateEvent { + public GpsUpdateEvent Gps { + get; private set; + } + + public PanicUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); + + public override String MqttTopic() => "panic/" + base.MqttTopic(); + + public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); + } +} diff --git a/Lora-Bot/Events/StatusUpdateEvent.cs b/Lora-Bot/Events/StatusUpdateEvent.cs new file mode 100644 index 0000000..e099d50 --- /dev/null +++ b/Lora-Bot/Events/StatusUpdateEvent.cs @@ -0,0 +1,40 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class StatusUpdateEvent : TrackerUpdateEvent { + public Int32 FrequencyOffset { + get; private set; + } + public String IpAddress { + get; private set; + } + public Int32 Version { + get; private set; + } + public Boolean WifiActive { + get; private set; + } + public String WifiSsid { + get; private set; + } + public String DeviceStatus { + get; private set; + } + + + public StatusUpdateEvent(Tracker tracker) : base(tracker) { + this.Version = tracker.Version; + this.IpAddress = tracker.IpAddress; + this.WifiSsid = tracker.WifiSsid; + this.WifiActive = tracker.WifiActive; + this.FrequencyOffset = tracker.FrequencyOffset; + this.DeviceStatus = tracker.DeviceStatus.ToString(); + } + + public override String MqttTopic() => "status/" + base.MqttTopic(); + + public override String ToString() => base.ToString() + " -- " + "Version: " + this.Version + " Ip-Address:" + this.IpAddress + " Wifi-SSID: " + this.WifiSsid + " Wifi-Active: " + this.WifiActive + " Freq-Offset: " + this.FrequencyOffset + " Status:" + this.DeviceStatus; + } +} diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs new file mode 100644 index 0000000..9c62811 --- /dev/null +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -0,0 +1,86 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class TrackerUpdateEvent : UpdateEventHelper { + public String Name { + get; private set; + } + public Double PacketRssi { + get; private set; + } + public Double Rssi { + get; private set; + } + public Double Snr { + get; private set; + } + public DateTime Receivedtime { + get; private set; + } + public Double BatteryLevel { + get; private set; + } + public Byte Recieverradio { + get; private set; + } + public Byte Recieverinterface { + get; private set; + } + public UInt32 Frequency { + get; private set; + } + public Int32 Bandwidth { + get; private set; + } + public Byte Codingrate { + get; private set; + } + public Byte Spreadingfactor { + get; private set; + } + public String Crcstatus { + get; private set; + } + public UInt16 Calculatedcrc { + get; private set; + } + public Double Snrmax { + get; private set; + } + public Double Snrmin { + get; private set; + } + public UInt32 Time { + get; private set; + } + public String Host => Environment.MachineName; + + public TrackerUpdateEvent(Tracker tracker) { + this.PacketRssi = tracker.PacketRssi; + this.Rssi = tracker.Rssi; + this.Snr = tracker.Snr; + this.Receivedtime = tracker.ReceivedTime; + this.Name = tracker.Name; + this.BatteryLevel = tracker.BatteryLevel; + this.Recieverradio = tracker.RecieverRadio; + this.Recieverinterface = tracker.RecieverInterface; + this.Frequency = tracker.Frequency; + this.Bandwidth = tracker.Bandwidth; + this.Codingrate = tracker.CodingRate; + this.Spreadingfactor = tracker.SpreadingFactor; + this.Crcstatus = tracker.CRCStatus; + this.Calculatedcrc = tracker.CalculatedCRC; + this.Snrmax = tracker.SnrMax; + this.Snrmin = tracker.SnrMin; + this.Time = tracker.Time; + } + + public override String MqttTopic() => base.MqttTopic() + this.Name; + + public override String ToString() => this.Name + " -- " + "Packet: PRssi: " + this.PacketRssi + " Rssi: " + this.Rssi + " SNR: (" + this.Snr + "/" + this.Snrmin + "/" + this.Snrmax + ") Time: " + this.Receivedtime.ToString() + + " Battery: " + this.BatteryLevel + " Radio: " + this.Recieverradio + " Interface: " + this.Recieverinterface + " Freq: " + this.Frequency + " BW: " + this.Bandwidth + + " CR: " + this.Codingrate + " SF: " + this.Spreadingfactor + " CRC: " + this.Crcstatus + "(0x" + this.Calculatedcrc.ToString("X4") + ") Time: " + this.Time; + } +} diff --git a/Lora-Bot/Events/UpdateEventHelper.cs b/Lora-Bot/Events/UpdateEventHelper.cs new file mode 100644 index 0000000..9b336a0 --- /dev/null +++ b/Lora-Bot/Events/UpdateEventHelper.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; + +using BlubbFish.Utils; +using BlubbFish.Utils.IoT.Interfaces; + +using LitJson; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class UpdateEventHelper : EventArgs, IMqtt { + public String ToJson() => JsonMapper.ToJson(this.ToDictionary()); + + public virtual Dictionary ToDictionary() { + Dictionary dictionary = new Dictionary(); + foreach(PropertyInfo item in this.GetType().GetProperties()) { + if(item.CanRead && item.GetValue(this) != null) { + if(item.GetValue(this).GetType().GetMethod("ToDictionary") != null) { + dictionary.Add(item.Name, item.GetValue(this).GetType().GetMethod("ToDictionary").Invoke(item.GetValue(this), null)); + } else if(item.GetValue(this).GetType().HasInterface(typeof(IDictionary))) { + Dictionary subdict = new Dictionary(); + foreach(DictionaryEntry subitem in (IDictionary)item.GetValue(this)) { + if(subitem.Value.GetType().GetMethod("ToDictionary") != null) { + subdict.Add(subitem.Key.ToString(), subitem.Value.GetType().GetMethod("ToDictionary").Invoke(subitem.Value, null)); + } + } + dictionary.Add(item.Name, subdict); + } else if(item.GetValue(this).GetType().BaseType == typeof(Enum)) { + dictionary.Add(item.Name, Helper.GetEnumDescription((Enum)item.GetValue(this))); + } else { + dictionary.Add(item.Name, item.GetValue(this)); + } + } + } + return dictionary; + } + + public virtual String MqttTopic() => ""; + } +} diff --git a/Lora-Bot/Models/GpsInfo.cs b/Lora-Bot/Models/GpsInfo.cs new file mode 100644 index 0000000..0b56e23 --- /dev/null +++ b/Lora-Bot/Models/GpsInfo.cs @@ -0,0 +1,88 @@ +using System; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { + public class GpsInfo { + public Double Latitude { + get; private set; + } + public Double LastLatitude { + get; private set; + } + public Double Longitude { + get; private set; + } + public Double LastLongitude { + get; private set; + } + public DateTime LastGPSPos { + get; private set; + } + public DateTime Time { + get; private set; + } + public Double Hdop { + get; private set; + } + public Boolean Fix { + get; private set; + } + public Double Height { + get; private set; + } + + public GpsInfo() { + this.Latitude = 0; + this.LastLatitude = 0; + this.Latitude = 0; + this.LastLongitude = 0; + this.Time = DateTime.MinValue; + this.Hdop = 99; + this.Fix = false; + this.Height = 0; + } + + public void SetUpdate(String str) { + String[] infos = str.Split(','); + + if(Double.TryParse(infos[0], out Double breitengrad)) { + this.Latitude = breitengrad; + } + if(Double.TryParse(infos[1], out Double laengengrad)) { + this.Longitude = laengengrad; + } + String d = DateTime.UtcNow.Day + "." + DateTime.UtcNow.Month + "." + DateTime.UtcNow.Year + " " + infos[2][0] + infos[2][1] + ":" + infos[2][2] + infos[2][3] + ":" + infos[2][4] + infos[2][5]; + if(DateTime.TryParse(d, out DateTime dv)) { + this.Time = dv; + } + if(Double.TryParse(infos[3], out Double hdop)) { + this.Hdop = hdop; + } + if(Double.TryParse(infos[4], out Double height)) { + this.Height = height; + } + this.Fix = !(Math.Abs(this.Latitude) < 0.000001 && Math.Abs(this.Longitude) < 0.000001); //Check for 0 lat and long + if(this.Fix) { + this.LastLongitude = this.Longitude; + this.LastLatitude = this.Latitude; + this.LastGPSPos = DateTime.UtcNow; + } + } + + public void SetUpdate(Single lat, Single lon, Single height, Single hdop, Byte hour, Byte minute, Byte second, Byte day, Byte month, UInt16 year) { + this.Latitude = lat; + this.Longitude = lon; + this.Height = height; + String d = day.ToString().PadLeft(2, '0') + "." + month.ToString().PadLeft(2, '0') + "." + year.ToString().PadLeft(4, '0') + " " + hour.ToString().PadLeft(2, '0') + ":" + minute.ToString().PadLeft(2, '0') + ":" + second.ToString().PadLeft(2, '0'); + if(DateTime.TryParse(d, out DateTime dv)) { + this.Time = dv; + } + this.Hdop = hdop; + this.Fix = lat != 0 && lon != 0; + if(this.Fix) { + this.LastLongitude = this.Longitude; + this.LastLatitude = this.Latitude; + this.LastGPSPos = DateTime.UtcNow; + } + } + } +} diff --git a/Lora-Bot/Models/Tracker.cs b/Lora-Bot/Models/Tracker.cs new file mode 100644 index 0000000..2b287ef --- /dev/null +++ b/Lora-Bot/Models/Tracker.cs @@ -0,0 +1,259 @@ +using System; +using System.Text.RegularExpressions; + +using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { + public class Tracker { + private enum ParseType { + Update, + Panic + } + + public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); + public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); + public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); + public event UpdateDataEvent DataUpdate; + public event UpdatePanicEvent PanicUpdate; + public event UpdateStatusEvent StatusUpdate; + + public Int32 Bandwidth { + get; private set; + } + public Double BatteryLevel { + get; private set; + } + public UInt16 CalculatedCRC { + get; private set; + } + public Byte CodingRate { + get; private set; + } + public String CRCStatus { + get; private set; + } + public Status DeviceStatus { + get; private set; + } + public UInt32 Frequency { + get; private set; + } + public Int32 FrequencyOffset { + get; private set; + } + public GpsInfo Gps { + get; private set; + } + public String IpAddress { + get; private set; + } + public String Modulation { + get; private set; + } + public String Name { + get; private set; + } + public Double PacketRssi { + get; private set; + } + public Byte RecieverInterface { + get; private set; + } + public Byte RecieverRadio { + get; private set; + } + public DateTime ReceivedTime { + get; private set; + } + public Double Rssi { + get; private set; + } + public Double Snr { + get; private set; + } + public Double SnrMax { + get; private set; + } + public Double SnrMin { + get; private set; + } + public Byte SpreadingFactor { + get; private set; + } + public UInt32 Time { + get; private set; + } + public Int32 Version { + get; private set; + } + public Boolean WifiActive { + get; private set; + } + public String WifiSsid { + get; private set; + } + + public enum Status { + Unknown, + Startup, + Powersave, + Shutdown + } + + public Tracker() => this.Gps = new GpsInfo(); + + #region Private Parsers and Helpers + private void Parse(Byte[] data, ParseType dataType) { + if(data.Length == 21) { + this.Name = GetName(data); + Single lat = BitConverter.ToSingle(data, 3); + Single lon = BitConverter.ToSingle(data, 7); + Single hdop = (Single)data[11] / 10; + Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; + Byte hour = data[14]; + Byte minute = data[15]; + Byte second = data[16]; + Byte day = data[17]; + Byte month = data[18]; + UInt16 year = (UInt16)(data[19] + 2000); + this.BatteryLevel = ((Single)data[20] + 230) / 100; + this.Gps.SetUpdate(lat, lon, height, hdop, hour, minute, second, day, month, year); + //Console.WriteLine("lat: " + lat + " lon: " + lon + " hdop: " + hdop + " heigt: " + height + " hh:mm:ss: " + hour + ":" + minute + ":" + second + " DD.MM.YY: " + day + "." + month + "." + year + " bat: " + this.BatteryLevel); + if(dataType == ParseType.Panic) { + this.PanicUpdate?.Invoke(this, new PanicUpdateEvent(this)); + } + this.DataUpdate?.Invoke(this, new DataUpdateEvent(this)); + } + } + + private void Parse(String text) { + String[] texts = text.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); + this.Name = GetName(text, 0); + String[] infos = texts[1].Split(','); + if(infos.Length >= 6 && Double.TryParse(infos[5], out Double batteryLevel)) { + this.BatteryLevel = batteryLevel; + } + this.Gps.SetUpdate(texts[1]); + this.DataUpdate?.Invoke(this, new DataUpdateEvent(this)); + } + + private void ParseStatus(String text) { + String[] texts = text.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); + if(texts.Length != 3) { + return; + } + this.Name = GetName(text, 1); + String[] infos = texts[2].Split(','); + if(infos.Length != 7) { + return; + } + if(Int32.TryParse(infos[0], out Int32 version)) { + this.Version = version; + } + this.IpAddress = infos[1]; + this.WifiSsid = infos[2]; + this.WifiActive = infos[3] == "t"; + if(Double.TryParse(infos[4], out Double batteryLevel)) { + this.BatteryLevel = batteryLevel; + } + if(Int32.TryParse(infos[5], out Int32 freqOffset)) { + this.FrequencyOffset = freqOffset; + } + if(Int32.TryParse(infos[6], out Int32 deviceStatus)) { + if(deviceStatus == 0) { + this.DeviceStatus = Status.Shutdown; + } else if(deviceStatus == 1) { + this.DeviceStatus = Status.Startup; + } else if(deviceStatus == 2) { + this.DeviceStatus = Status.Powersave; + } + } + this.StatusUpdate?.Invoke(this, new StatusUpdateEvent(this)); + } + + private void SetUpdate(LoraClientEvent e) { + if(e is Ic800ALoraClientEvent) { + Ic800ALoraClientEvent ic = e as Ic800ALoraClientEvent; + this.Bandwidth = ic.Bandwidth; + this.CalculatedCRC = ic.Calculatedcrc; + this.CodingRate = ic.CodingRate; + this.CRCStatus = ic.CrcStatus; + this.Frequency = ic.Frequency; + this.RecieverInterface = ic.Interface; + this.Modulation = ic.Modulation; + this.RecieverRadio = ic.Radio; + this.SnrMax = ic.SnrMax; + this.SnrMin = ic.SnrMin; + this.SpreadingFactor = ic.Spreadingfactor; + this.Time = ic.Time; + } + this.PacketRssi = e.Packetrssi; + this.Rssi = e.Rssi; + this.Snr = e.Snr; + this.ReceivedTime = e.UpdateTime; + } + #endregion + + #region External update Methods + public void SetUpdate(LoraClientEvent e, String data) { + this.SetUpdate(e); + this.Parse(data); + } + + public void SetUpdate(LoraClientEvent e, Byte[] data) { + this.SetUpdate(e); + this.Parse(data, ParseType.Update); + } + public void SetPanics(LoraClientEvent e, Byte[] data) { + this.SetUpdate(e); + this.Parse(data, ParseType.Panic); + } + + public void SetStatus(LoraClientEvent e, String textStatus) { + this.SetUpdate(e); + this.ParseStatus(textStatus); + } + #endregion + + #region Static Functions + public static Boolean CheckPacket(String message) { + String[] m; + if(message.Contains("\r\n")) { + m = message.Split(new String[] { "\r\n" }, StringSplitOptions.None); + } else if(message.Contains("\n")) { + m = message.Split(new String[] { "\n" }, StringSplitOptions.None); + } else { + return false; + } + if(m.Length == 2) { //Normal Data Packet + return m[0] == "" ? false : Regex.Match(m[1], "[0-9]+.[0-9]{5,10},[0-9]+.[0-9]{5,10},[0-9]{6},[0-9]+.[0-9]{2},[0-9]+.[0-9],[0-9].[0-9]{2}").Success; + } + if(m.Length == 3) { //Debug Packet + if(m[0] != "deb") { //first must be "deb" + return false; + } + if(m[1] == "") { //Name should not be empty + return false; + } + //version,ip,ssid,wififlag,battery,offset,statusmode + return Regex.Match(m[2], "^[0-9]+,[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3},[^,]+,[tf],[0-9].[0-9]{2},(-[0-9]+|[0-9]+),[0-9]").Success; + } + return false; + } + + public static String GetName(String message, Int32 index) => message.Contains("\r\n") ? message.Split(new String[] { "\r\n" }, StringSplitOptions.None)[index].Trim() : message.Contains("\n") ? message.Split(new String[] { "\n" }, StringSplitOptions.None)[index].Trim() : ""; + + public static String GetName(Byte[] data) { + if(data.Length >= 3) { + Byte[] ret = new Byte[2]; + for(Int32 i = 0; i < 2; i++) { + ret[i] = data[i + 1]; + } + return ret[1] == 0 ? System.Text.Encoding.ASCII.GetString(new Byte[] { ret[0] }).Trim() : System.Text.Encoding.ASCII.GetString(ret).Trim(); + } + return ""; + } + #endregion + } +} diff --git a/Lora-Bot/Moduls/Mqtt.cs b/Lora-Bot/Moduls/Mqtt.cs index 6fcb0dd..7c6338f 100644 --- a/Lora-Bot/Moduls/Mqtt.cs +++ b/Lora-Bot/Moduls/Mqtt.cs @@ -7,7 +7,7 @@ using Fraunhofer.Fit.Iot.Lora; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls { - class Mqtt : Mqtt { + /*class Mqtt : Mqtt { public override event ModulEvent Update; public Mqtt(LoraController lib, InIReader settings) : base(lib, settings) { } @@ -31,5 +31,5 @@ protected override void LibUpadteThread(Object state) { Helper.WriteError("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls.Mqtt.LibUpadteThread: " + e.Message); } } - } + }*/ } diff --git a/Lora-Bot/Moduls/Txtout.cs b/Lora-Bot/Moduls/Txtout.cs index 5787584..6a76529 100644 --- a/Lora-Bot/Moduls/Txtout.cs +++ b/Lora-Bot/Moduls/Txtout.cs @@ -8,7 +8,7 @@ using Fraunhofer.Fit.Iot.Lora.Events; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls { - public class Txtout : AModul { + /*public class Txtout : AModul { public override event ModulEvent Update; private readonly String filename; @@ -43,5 +43,5 @@ public override void Dispose() { } protected override void UpdateConfig() {} - } + }*/ } \ No newline at end of file diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs new file mode 100644 index 0000000..f4d414e --- /dev/null +++ b/Lora-Bot/Parser/LoraParser.cs @@ -0,0 +1,20 @@ +using System; + +using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Parser { + class LoraParser { + public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); + public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); + public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); + public event UpdateDataEvent DataUpdate; + public event UpdatePanicEvent PanicUpdate; + public event UpdateStatusEvent StatusUpdate; + + + internal void ReceivedPacket(Object _, RecievedData e) { + + } + } +} diff --git a/Lora-Bot/Program.cs b/Lora-Bot/Program.cs index 67934e5..6f30402 100644 --- a/Lora-Bot/Program.cs +++ b/Lora-Bot/Program.cs @@ -1,46 +1,48 @@ using System; using System.Collections.Generic; + using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots; + using Fraunhofer.Fit.Iot.Lora; using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; namespace Fraunhofer.Fit.IoT.Bots.LoraBot { - class Program : Bot { + class Program : Bot { static void Main(String[] args) => new Program(args); public Program(String[] _) { InIReader.SetSearchPath(new List() { "/etc/lorabot", Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\lorabot" }); - if (!InIReader.ConfigExist("settings")) { + if(!InIReader.ConfigExist("settings")) { Helper.WriteError("No settings.ini found. Abord!"); return; } InIReader settings = InIReader.GetInstance("settings"); this.logger.SetPath(settings.GetValue("logging", "path")); - if (settings.GetValue("lora","debug") == "true") { - LoraController lora = new LoraController(settings.GetSection("lora"), false); - lora.Dispose(); - } else { - LoraController lora = new LoraController(settings.GetSection("lora")); - this.ModulLoader("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls", lora); - this.ModulInterconnect(); - this.ModulEvents(); - lora.DataUpdate += this.LoraDataUpdate; - lora.StatusUpdate += this.LoraStatusUpdate; - lora.PanicUpdate += this.LoraPanicUpdate; - this.WaitForShutdown(); - Console.WriteLine("after wait"); - this.ModulDispose(); - Console.WriteLine("after dispose"); - lora.Dispose(); - Console.WriteLine("after loradisp"); - } - } - private void LoraPanicUpdate(Object sender, PanicUpdateEvent e) => Console.WriteLine("-> Lora-Panic: " + e.ToString()); + LoraController lora = new LoraController(settings.GetSection("lora")); + LoraParser parser = new LoraParser(); + + lora.Received += parser.ReceivedPacket; - private void LoraStatusUpdate(Object sender, StatusUpdateEvent e) => Console.WriteLine("-> Lora-Status: " + e.ToString()); + this.ModulLoader("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls", parser); + this.ModulInterconnect(); + this.ModulEvents(); - private void LoraDataUpdate(Object sender, DataUpdateEvent e) => Console.WriteLine("-> Lora-Data: " + e.ToString()); + lora.Received += this.Lora_Received; + lora.Transmitted += this.Lora_Transmitted; + + this.WaitForShutdown(); + Console.WriteLine("after wait"); + + this.ModulDispose(); + Console.WriteLine("after dispose"); + + lora.Dispose(); + Console.WriteLine("after loradisp"); + } + private void Lora_Transmitted(Object sender, TransmittedData e) => Console.WriteLine("-> " + e.ToString()); + private void Lora_Received(Object sender, RecievedData e) => Console.WriteLine("<- " + e.ToString()); } } diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 924cd0b..36b4ffd 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -2,14 +2,24 @@ path=/var/log/lorabot.log ;[lora] -;type=Draginolora -;pin_sspin=Pin06 -;pin_dio0=Pin07 -;pin_rst=Pin00 -;frequency=868100000 -;spreadingfactor=8 -;signalbandwith=125000 -;codingrate=6 +;debug=true +;type=Dragino +;pin_sspin=Pin25 +;pin_dio0=Pin04 +;pin_rst=Pin17 +;spichan=Channel0 +;freq=867000000 +;sf=10 +;bw=125000 +;cr=7 +;;18 = 0x12 +;syncword=18 +;preamblelength=8 +;currentlimit=140 +;power=17 +;gain=0 + + [lora] type=Ic880alora diff --git a/README.md b/README.md index f7e6c9b..ae97f5c 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,9 @@ To install dotnet on a Raspi: ```bash wget [download link] sudo mkdir /usr/share/dotnet -export PATH=$PATH:/usr/share/dotnet/ sudo tar zxf dotnet-runtime-3.1.0-linux-arm.tar.gz -C /usr/share/dotnet +rm dotnet-runtime-3.1.0-linux-arm.tar.gz +sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet ``` ## Contributing From 2d8523cabe14817a4e35458a5a8fd01319f34c37 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Fri, 20 Dec 2019 19:29:59 +0100 Subject: [PATCH 06/29] Moved stuff from Lora to here, also rewrite parsing completely --- Lora-Bot/Events/DataUpdateEvent.cs | 4 +- Lora-Bot/Events/GpsUpdateEvent.cs | 38 +++++---- Lora-Bot/Events/PanicUpdateEvent.cs | 4 +- Lora-Bot/Events/StatusUpdateEvent.cs | 16 ++-- Lora-Bot/Events/TrackerUpdateEvent.cs | 41 +++++++--- Lora-Bot/Models/BinaryPacket.cs | 65 +++++++++++++++ Lora-Bot/Models/DebugPacket.cs | 51 ++++++++++++ Lora-Bot/Models/GpsInfo.cs | 4 +- Lora-Bot/Models/Packet.cs | 34 ++++++++ Lora-Bot/Models/Tracker.cs | 16 ++-- Lora-Bot/Moduls/Txtout.cs | 2 +- Lora-Bot/Parser/LoraParser.cs | 111 +++++++++++++++++++++++++- Lora-Bot/Program.cs | 7 +- 13 files changed, 339 insertions(+), 54 deletions(-) create mode 100644 Lora-Bot/Models/BinaryPacket.cs create mode 100644 Lora-Bot/Models/DebugPacket.cs create mode 100644 Lora-Bot/Models/Packet.cs diff --git a/Lora-Bot/Events/DataUpdateEvent.cs b/Lora-Bot/Events/DataUpdateEvent.cs index ad0d97e..7b1b16f 100644 --- a/Lora-Bot/Events/DataUpdateEvent.cs +++ b/Lora-Bot/Events/DataUpdateEvent.cs @@ -5,10 +5,10 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class DataUpdateEvent : TrackerUpdateEvent { public GpsUpdateEvent Gps { - get; private set; + get; set; } - public DataUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); + //public DataUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); public override String MqttTopic() => "data/" + base.MqttTopic(); diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs index ef8fae0..eec45fd 100644 --- a/Lora-Bot/Events/GpsUpdateEvent.cs +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -1,25 +1,34 @@ using System; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; - namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class GpsUpdateEvent : UpdateEventHelper { + #region GPS-Fields public Boolean Fix { - get; private set; + get; set; } + public Double Hdop { - get; private set; + get; set; } + public Double Height { - get; private set; + get; set; } + public Double Latitude { - get; private set; + get; set; } + public Double Longitude { - get; private set; + get; set; + } + + public DateTime Time { + get; set; } - public Double LastLatitude { + #endregion + //Should do by client + /*public Double LastLatitude { get; private set; } public Double LastLongitude { @@ -27,12 +36,9 @@ public Double LastLongitude { } public DateTime LastGPSPos { get; private set; - } - public DateTime Time { - get; private set; - } + }*/ - public GpsUpdateEvent(GpsInfo gps) { + /*public GpsUpdateEvent(GpsInfo gps) { this.Fix = gps.Fix; this.Hdop = gps.Hdop; this.Height = gps.Height; @@ -42,8 +48,10 @@ public GpsUpdateEvent(GpsInfo gps) { this.LastLatitude = gps.LastLatitude; this.LastLongitude = gps.LastLongitude; this.LastGPSPos = gps.LastGPSPos; - } + }*/ + + //public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; - public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; + public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; } } diff --git a/Lora-Bot/Events/PanicUpdateEvent.cs b/Lora-Bot/Events/PanicUpdateEvent.cs index 5f13453..14961fc 100644 --- a/Lora-Bot/Events/PanicUpdateEvent.cs +++ b/Lora-Bot/Events/PanicUpdateEvent.cs @@ -5,10 +5,10 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class PanicUpdateEvent : TrackerUpdateEvent { public GpsUpdateEvent Gps { - get; private set; + get; set; } - public PanicUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); + //public PanicUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); public override String MqttTopic() => "panic/" + base.MqttTopic(); diff --git a/Lora-Bot/Events/StatusUpdateEvent.cs b/Lora-Bot/Events/StatusUpdateEvent.cs index e099d50..19924dc 100644 --- a/Lora-Bot/Events/StatusUpdateEvent.cs +++ b/Lora-Bot/Events/StatusUpdateEvent.cs @@ -5,33 +5,33 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class StatusUpdateEvent : TrackerUpdateEvent { public Int32 FrequencyOffset { - get; private set; + get; set; } public String IpAddress { - get; private set; + get; set; } public Int32 Version { - get; private set; + get; set; } public Boolean WifiActive { - get; private set; + get; set; } public String WifiSsid { - get; private set; + get; set; } public String DeviceStatus { - get; private set; + get; set; } - public StatusUpdateEvent(Tracker tracker) : base(tracker) { + /*public StatusUpdateEvent(Tracker tracker) : base(tracker) { this.Version = tracker.Version; this.IpAddress = tracker.IpAddress; this.WifiSsid = tracker.WifiSsid; this.WifiActive = tracker.WifiActive; this.FrequencyOffset = tracker.FrequencyOffset; this.DeviceStatus = tracker.DeviceStatus.ToString(); - } + }*/ public override String MqttTopic() => "status/" + base.MqttTopic(); diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs index 9c62811..03cd94a 100644 --- a/Lora-Bot/Events/TrackerUpdateEvent.cs +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -4,24 +4,44 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class TrackerUpdateEvent : UpdateEventHelper { + #region General Tracker data public String Name { - get; private set; + get; set; } - public Double PacketRssi { - get; private set; + + public Double BatteryLevel { + get; set; } + #endregion + + #region Global Lora Data public Double Rssi { - get; private set; + get; set; } + public Double Snr { + get; set; + } + + public Double PacketRssi { get; private set; } + + public String Crcstatus { + get; set; + } + public DateTime Receivedtime { - get; private set; + get; set; } - public Double BatteryLevel { - get; private set; + #endregion + + #region Dragino Special Data + public Double Freqerror { + get; set; } + #endregion + public Byte Recieverradio { get; private set; } @@ -40,9 +60,6 @@ public Byte Codingrate { public Byte Spreadingfactor { get; private set; } - public String Crcstatus { - get; private set; - } public UInt16 Calculatedcrc { get; private set; } @@ -57,7 +74,7 @@ public UInt32 Time { } public String Host => Environment.MachineName; - public TrackerUpdateEvent(Tracker tracker) { + /*public TrackerUpdateEvent(Tracker tracker) { this.PacketRssi = tracker.PacketRssi; this.Rssi = tracker.Rssi; this.Snr = tracker.Snr; @@ -75,7 +92,7 @@ public TrackerUpdateEvent(Tracker tracker) { this.Snrmax = tracker.SnrMax; this.Snrmin = tracker.SnrMin; this.Time = tracker.Time; - } + }*/ public override String MqttTopic() => base.MqttTopic() + this.Name; diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs new file mode 100644 index 0000000..52c960e --- /dev/null +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -0,0 +1,65 @@ +using System; + +using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { + public class BinaryPacket : Packet { + public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, DateTime date, Single battery, RecievedData recieveddata) { + if(typ == LoraParser.Typ.Data) { + this.Data = new DataUpdateEvent() { + Name = name, + BatteryLevel = battery, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Time = date, + Fix = lat != 0 || lon != 0 + } + }; + this.Type = Typ.Data; + this.SetLoraData(recieveddata, this.Data); + } else if(typ == LoraParser.Typ.Panic) { + this.Panic = new PanicUpdateEvent() { + Name = name, + BatteryLevel = battery, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Time = date, + Fix = lat != 0 || lon != 0 + } + }; + this.Type = Typ.Panic; + this.SetLoraData(recieveddata, this.Panic); + } else { + this.Type = Typ.Error; + } + } + + public enum Typ { + Data, + Panic, + Error + } + + public Typ Type { + get; set; + } + + public DataUpdateEvent Data { + get; + private set; + } + + public PanicUpdateEvent Panic { + get; + private set; + } + } +} diff --git a/Lora-Bot/Models/DebugPacket.cs b/Lora-Bot/Models/DebugPacket.cs new file mode 100644 index 0000000..d6c1f06 --- /dev/null +++ b/Lora-Bot/Models/DebugPacket.cs @@ -0,0 +1,51 @@ +using System; + +using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { + class DebugPacket : Packet { + public DebugPacket(String text, String name, Int32 version, String ipaddress, String wifissid, Boolean wifiactive, Double batteryLevel, Int32 freqOffset, LoraParser.Status devicestatus, RecievedData recieveddata) { + this.Text = text; + if(devicestatus == LoraParser.Status.Unknown) { + this.Type = Typ.Error; + } else { + this.Status = new StatusUpdateEvent() { + Name = name, + BatteryLevel = batteryLevel, + Version = version, + IpAddress = ipaddress, + WifiSsid = wifissid, + WifiActive = wifiactive, + FrequencyOffset = freqOffset, + DeviceStatus = devicestatus.ToString() + }; + this.SetLoraData(recieveddata, this.Status); + } + + } + + public DebugPacket() { + } + + public enum Typ { + Status, + Error + } + + public Typ Type { + get; set; + } + + public String Text { + get; + private set; + } + + public StatusUpdateEvent Status { + get; + private set; + } + } +} diff --git a/Lora-Bot/Models/GpsInfo.cs b/Lora-Bot/Models/GpsInfo.cs index 0b56e23..1d99111 100644 --- a/Lora-Bot/Models/GpsInfo.cs +++ b/Lora-Bot/Models/GpsInfo.cs @@ -1,7 +1,7 @@ using System; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { - public class GpsInfo { + /*public class GpsInfo { public Double Latitude { get; private set; } @@ -84,5 +84,5 @@ public void SetUpdate(Single lat, Single lon, Single height, Single hdop, Byte h this.LastGPSPos = DateTime.UtcNow; } } - } + }*/ } diff --git a/Lora-Bot/Models/Packet.cs b/Lora-Bot/Models/Packet.cs new file mode 100644 index 0000000..215b893 --- /dev/null +++ b/Lora-Bot/Models/Packet.cs @@ -0,0 +1,34 @@ + +using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { + public class Packet { + + protected void SetLoraData(RecievedData e, TrackerUpdateEvent data) { + /*if(e is Ic800ALoraClientEvent) { + Ic800ALoraClientEvent ic = e as Ic800ALoraClientEvent; + this.Bandwidth = ic.Bandwidth; + this.CalculatedCRC = ic.Calculatedcrc; + this.CodingRate = ic.CodingRate; + this.CRCStatus = ic.CrcStatus; + this.Frequency = ic.Frequency; + this.RecieverInterface = ic.Interface; + this.Modulation = ic.Modulation; + this.RecieverRadio = ic.Radio; + this.SnrMax = ic.SnrMax; + this.SnrMin = ic.SnrMin; + this.SpreadingFactor = ic.Spreadingfactor; + this.Time = ic.Time; + }*/ + if(e is DragionoRecievedObj) { + DragionoRecievedObj dragino = e as DragionoRecievedObj; + data.Freqerror = dragino.FreqError; + } + data.Rssi = e.Rssi; + data.Snr = e.Snr; + data.Crcstatus = e.Crc ? "Ok" : "Bad"; + data.Receivedtime = e.RecievedTime; + } + } +} diff --git a/Lora-Bot/Models/Tracker.cs b/Lora-Bot/Models/Tracker.cs index 2b287ef..c455414 100644 --- a/Lora-Bot/Models/Tracker.cs +++ b/Lora-Bot/Models/Tracker.cs @@ -6,7 +6,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class Tracker { - private enum ParseType { + /*private enum ParseType { Update, Panic } @@ -16,9 +16,9 @@ private enum ParseType { public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); public event UpdateDataEvent DataUpdate; public event UpdatePanicEvent PanicUpdate; - public event UpdateStatusEvent StatusUpdate; + public event UpdateStatusEvent StatusUpdate;*/ - public Int32 Bandwidth { + /*public Int32 Bandwidth { get; private set; } public Double BatteryLevel { @@ -101,10 +101,10 @@ public enum Status { Shutdown } - public Tracker() => this.Gps = new GpsInfo(); + public Tracker() => this.Gps = new GpsInfo();*/ #region Private Parsers and Helpers - private void Parse(Byte[] data, ParseType dataType) { + /*private void Parse(Byte[] data, ParseType dataType) { if(data.Length == 21) { this.Name = GetName(data); Single lat = BitConverter.ToSingle(data, 3); @@ -213,11 +213,11 @@ public void SetPanics(LoraClientEvent e, Byte[] data) { public void SetStatus(LoraClientEvent e, String textStatus) { this.SetUpdate(e); this.ParseStatus(textStatus); - } + }*/ #endregion #region Static Functions - public static Boolean CheckPacket(String message) { + /*public static Boolean CheckPacket(String message) { String[] m; if(message.Contains("\r\n")) { m = message.Split(new String[] { "\r\n" }, StringSplitOptions.None); @@ -253,7 +253,7 @@ public static String GetName(Byte[] data) { return ret[1] == 0 ? System.Text.Encoding.ASCII.GetString(new Byte[] { ret[0] }).Trim() : System.Text.Encoding.ASCII.GetString(ret).Trim(); } return ""; - } + }*/ #endregion } } diff --git a/Lora-Bot/Moduls/Txtout.cs b/Lora-Bot/Moduls/Txtout.cs index 6a76529..e8b8b1a 100644 --- a/Lora-Bot/Moduls/Txtout.cs +++ b/Lora-Bot/Moduls/Txtout.cs @@ -4,7 +4,7 @@ using BlubbFish.Utils.IoT.Bots.Events; using BlubbFish.Utils.IoT.Bots.Moduls; using Fraunhofer.Fit.Iot.Lora; -using Fraunhofer.Fit.Iot.Lora.Trackers; +//using Fraunhofer.Fit.Iot.Lora.Trackers; using Fraunhofer.Fit.Iot.Lora.Events; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls { diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index f4d414e..0a5a52a 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -1,10 +1,14 @@ using System; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; using Fraunhofer.Fit.Iot.Lora.Events; using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Parser { - class LoraParser { + public class LoraParser { public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); @@ -12,9 +16,112 @@ class LoraParser { public event UpdatePanicEvent PanicUpdate; public event UpdateStatusEvent StatusUpdate; + public enum Status { + Unknown, + Startup, + Powersave, + Shutdown + } + + public enum Typ { + Data, + Panic, + Unknown + } + + private async void DataUpdates(Object sender, DataUpdateEvent e) => await Task.Run(() => this.DataUpdate?.Invoke(sender, e)); + + private async void PanicUpdates(Object sender, PanicUpdateEvent e) => await Task.Run(() => this.PanicUpdate?.Invoke(sender, e)); + + private async void StatusUpdates(Object sender, StatusUpdateEvent e) => await Task.Run(() => this.StatusUpdate?.Invoke(sender, e)); - internal void ReceivedPacket(Object _, RecievedData e) { + internal void ReceivedPacket(Object sender, RecievedData e) { + if(e.Data.Length == 21 && e.Data[0] == 'b' || e.Data[0] == 'p') { + //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### + BinaryPacket p = this.ParseBinaryPacket(e.Data, e); + if(p.Type == BinaryPacket.Typ.Data) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); + this.DataUpdates(sender, p.Data); + } else if(p.Type == BinaryPacket.Typ.Panic) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); + this.PanicUpdates(sender, p.Panic); + } else { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| CRC:" + e.Crc); + } + } else if(e.Data.Length > 3 && e.Data[0] == 'd' && e.Data[1] == 'e' && e.Data[2] == 'b') { + //###### Debug Packet, three lines ############# + DebugPacket p = this.ParseDebugPacket(e.Data, e); + if(p.Type == DebugPacket.Typ.Status) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Status |" + this.ToStringFilter(p.Text) + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); + this.StatusUpdates(sender, p.Status); + } else { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Debug-Packet not Match! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| CRC:" + e.Crc); + } + } else { + //###### Every else Packet ############# + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Some other Packet! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| '" + this.ToStringFilter(e.Data) + "' RSSI:" + e.Rssi + " SNR:" + e.Snr); + } + } + + private String ToStringFilter(Byte[] data) => this.ToStringFilter(Encoding.ASCII.GetString(data).Trim()); + + private String ToStringFilter(String data) { + String text = Regex.Replace(data, "^[^a-zA-Z0-9,.\\-+;:()[\\]\\/]$", "-"); + text = text.Replace("\n", "-"); + return text.Replace("\r", "-"); + } + + private DebugPacket ParseDebugPacket(Byte[] data, RecievedData recieveddata) { + String text = Encoding.ASCII.GetString(data).Trim(); + String[] m; + if(text.Contains("\r\n")) { + m = text.Split(new String[] { "\r\n" }, StringSplitOptions.None); + } else if(text.Contains("\n")) { + m = text.Split(new String[] { "\n" }, StringSplitOptions.None); + } else { + return new DebugPacket() { Type = DebugPacket.Typ.Error }; + } + //version,ip,ssid,wififlag,battery,offset,statusmode + if(m.Length == 3 && m[0] == "deb" && m[1] != "" && Regex.Match(m[2], "^[0-9]+,[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3},[^,]+,[tf],[0-9].[0-9]{2},(-[0-9]+|[0-9]+),[0-9]$").Success) { + String name = m[1].Trim(); + String[] infos = m[2].Split(','); + _ = Int32.TryParse(infos[0], out Int32 version); + String ipaddress = infos[1]; + String wifissid = infos[2]; + Boolean wifiactive = infos[3] == "t"; + _ = Double.TryParse(infos[4], out Double batteryLevel); + _ = Int32.TryParse(infos[5], out Int32 freqOffset); + Status status = Status.Unknown; + if(Int32.TryParse(infos[6], out Int32 deviceStatus)) { + if(deviceStatus == 0) { + status = Status.Shutdown; + } else if(deviceStatus == 1) { + status = Status.Startup; + } else if(deviceStatus == 2) { + status = Status.Powersave; + } + } + return new DebugPacket(text, name, version, ipaddress, wifissid, wifiactive, batteryLevel, freqOffset, status, recieveddata); + } else { + return new DebugPacket() { Type = DebugPacket.Typ.Error }; + } + } + private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { + Typ typ = Typ.Unknown; + if(data[0] == 'b') { + typ = Typ.Data; + } else if(data[0] == 'p') { + typ = Typ.Panic; + } + String name = data[2] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[1] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[2] }).Trim(); + Single lat = BitConverter.ToSingle(data, 3); + Single lon = BitConverter.ToSingle(data, 7); + Single hdop = (Single)data[11] / 10; + Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; + DateTime date = DateTime.TryParse(data[17].ToString().PadLeft(2, '0') + "." + data[18].ToString().PadLeft(2, '0') + "." + ((UInt16)(data[19] + 2000)).ToString().PadLeft(4, '0') + " " + data[14].ToString().PadLeft(2, '0') + ":" + data[15].ToString().PadLeft(2, '0') + ":" + data[16].ToString().PadLeft(2, '0'), out DateTime dv) ? dv : DateTime.MinValue; + Single battery = ((Single)data[20] + 230) / 100; + return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata); } } } diff --git a/Lora-Bot/Program.cs b/Lora-Bot/Program.cs index 6f30402..ce4e889 100644 --- a/Lora-Bot/Program.cs +++ b/Lora-Bot/Program.cs @@ -6,6 +6,7 @@ using Fraunhofer.Fit.Iot.Lora; using Fraunhofer.Fit.Iot.Lora.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; namespace Fraunhofer.Fit.IoT.Bots.LoraBot { @@ -29,7 +30,9 @@ public Program(String[] _) { this.ModulInterconnect(); this.ModulEvents(); - lora.Received += this.Lora_Received; + parser.DataUpdate += this.Lora_Parsed; + parser.PanicUpdate += this.Lora_Parsed; + parser.StatusUpdate += this.Lora_Parsed; lora.Transmitted += this.Lora_Transmitted; this.WaitForShutdown(); @@ -43,6 +46,6 @@ public Program(String[] _) { } private void Lora_Transmitted(Object sender, TransmittedData e) => Console.WriteLine("-> " + e.ToString()); - private void Lora_Received(Object sender, RecievedData e) => Console.WriteLine("<- " + e.ToString()); + private void Lora_Parsed(Object sender, TrackerUpdateEvent e) => Console.WriteLine("<- " + e.ToString()); } } From 3e163f0858e62945637a273ee4b1b9675fbd0484 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 21 Dec 2019 01:37:23 +0100 Subject: [PATCH 07/29] REfactoring mostly done --- Lora-Bot/Events/DataUpdateEvent.cs | 4 -- Lora-Bot/Events/GpsUpdateEvent.cs | 35 +++++-------- Lora-Bot/Events/PanicUpdateEvent.cs | 4 -- Lora-Bot/Events/StatusUpdateEvent.cs | 17 ++---- Lora-Bot/Events/TrackerUpdateEvent.cs | 22 -------- Lora-Bot/Models/BinaryPacket.cs | 7 ++- Lora-Bot/Models/Packet.cs | 12 ++--- Lora-Bot/Models/Tracker.cs | 20 ++++---- Lora-Bot/Moduls/Mqtt.cs | 10 ++-- Lora-Bot/Moduls/Txtout.cs | 13 ++--- Lora-Bot/Parser/LoraParser.cs | 74 ++++++++++++++++++--------- 11 files changed, 102 insertions(+), 116 deletions(-) diff --git a/Lora-Bot/Events/DataUpdateEvent.cs b/Lora-Bot/Events/DataUpdateEvent.cs index 7b1b16f..d7bd7a9 100644 --- a/Lora-Bot/Events/DataUpdateEvent.cs +++ b/Lora-Bot/Events/DataUpdateEvent.cs @@ -1,15 +1,11 @@ using System; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; - namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class DataUpdateEvent : TrackerUpdateEvent { public GpsUpdateEvent Gps { get; set; } - //public DataUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); - public override String MqttTopic() => "data/" + base.MqttTopic(); public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs index eec45fd..65fe065 100644 --- a/Lora-Bot/Events/GpsUpdateEvent.cs +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -27,31 +27,22 @@ public DateTime Time { get; set; } #endregion - //Should do by client - /*public Double LastLatitude { - get; private set; + + [Obsolete("Should do by client")] + public Double LastLatitude { + get; set; } + [Obsolete("Should do by client")] public Double LastLongitude { - get; private set; + get; set; } + [Obsolete("Should do by client")] public DateTime LastGPSPos { - get; private set; - }*/ - - /*public GpsUpdateEvent(GpsInfo gps) { - this.Fix = gps.Fix; - this.Hdop = gps.Hdop; - this.Height = gps.Height; - this.Latitude = gps.Latitude; - this.Longitude = gps.Longitude; - this.Time = gps.Time; - this.LastLatitude = gps.LastLatitude; - this.LastLongitude = gps.LastLongitude; - this.LastGPSPos = gps.LastGPSPos; - }*/ - - //public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; - - public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; + get; set; + } + + public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; + + //public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; } } diff --git a/Lora-Bot/Events/PanicUpdateEvent.cs b/Lora-Bot/Events/PanicUpdateEvent.cs index 14961fc..ebdbe91 100644 --- a/Lora-Bot/Events/PanicUpdateEvent.cs +++ b/Lora-Bot/Events/PanicUpdateEvent.cs @@ -1,15 +1,11 @@ using System; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; - namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class PanicUpdateEvent : TrackerUpdateEvent { public GpsUpdateEvent Gps { get; set; } - //public PanicUpdateEvent(Tracker tracker) : base(tracker) => this.Gps = new GpsUpdateEvent(tracker.Gps); - public override String MqttTopic() => "panic/" + base.MqttTopic(); public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); diff --git a/Lora-Bot/Events/StatusUpdateEvent.cs b/Lora-Bot/Events/StatusUpdateEvent.cs index 19924dc..3005270 100644 --- a/Lora-Bot/Events/StatusUpdateEvent.cs +++ b/Lora-Bot/Events/StatusUpdateEvent.cs @@ -1,38 +1,31 @@ using System; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; - namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class StatusUpdateEvent : TrackerUpdateEvent { public Int32 FrequencyOffset { get; set; } + public String IpAddress { get; set; } + public Int32 Version { get; set; } + public Boolean WifiActive { get; set; } + public String WifiSsid { get; set; } + public String DeviceStatus { get; set; } - - /*public StatusUpdateEvent(Tracker tracker) : base(tracker) { - this.Version = tracker.Version; - this.IpAddress = tracker.IpAddress; - this.WifiSsid = tracker.WifiSsid; - this.WifiActive = tracker.WifiActive; - this.FrequencyOffset = tracker.FrequencyOffset; - this.DeviceStatus = tracker.DeviceStatus.ToString(); - }*/ - public override String MqttTopic() => "status/" + base.MqttTopic(); public override String ToString() => base.ToString() + " -- " + "Version: " + this.Version + " Ip-Address:" + this.IpAddress + " Wifi-SSID: " + this.WifiSsid + " Wifi-Active: " + this.WifiActive + " Freq-Offset: " + this.FrequencyOffset + " Status:" + this.DeviceStatus; diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs index 03cd94a..954c84f 100644 --- a/Lora-Bot/Events/TrackerUpdateEvent.cs +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -1,7 +1,5 @@ using System; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; - namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { public class TrackerUpdateEvent : UpdateEventHelper { #region General Tracker data @@ -74,26 +72,6 @@ public UInt32 Time { } public String Host => Environment.MachineName; - /*public TrackerUpdateEvent(Tracker tracker) { - this.PacketRssi = tracker.PacketRssi; - this.Rssi = tracker.Rssi; - this.Snr = tracker.Snr; - this.Receivedtime = tracker.ReceivedTime; - this.Name = tracker.Name; - this.BatteryLevel = tracker.BatteryLevel; - this.Recieverradio = tracker.RecieverRadio; - this.Recieverinterface = tracker.RecieverInterface; - this.Frequency = tracker.Frequency; - this.Bandwidth = tracker.Bandwidth; - this.Codingrate = tracker.CodingRate; - this.Spreadingfactor = tracker.SpreadingFactor; - this.Crcstatus = tracker.CRCStatus; - this.Calculatedcrc = tracker.CalculatedCRC; - this.Snrmax = tracker.SnrMax; - this.Snrmin = tracker.SnrMin; - this.Time = tracker.Time; - }*/ - public override String MqttTopic() => base.MqttTopic() + this.Name; public override String ToString() => this.Name + " -- " + "Packet: PRssi: " + this.PacketRssi + " Rssi: " + this.Rssi + " SNR: (" + this.Snr + "/" + this.Snrmin + "/" + this.Snrmax + ") Time: " + this.Receivedtime.ToString() + diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs index 52c960e..37e0f25 100644 --- a/Lora-Bot/Models/BinaryPacket.cs +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -6,7 +6,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class BinaryPacket : Packet { - public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, DateTime date, Single battery, RecievedData recieveddata) { + public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, DateTime date, Single battery, RecievedData recieveddata, Tuple old) { if(typ == LoraParser.Typ.Data) { this.Data = new DataUpdateEvent() { Name = name, @@ -17,7 +17,10 @@ public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Sin Hdop = hdop, Height = height, Time = date, - Fix = lat != 0 || lon != 0 + Fix = lat != 0 || lon != 0, + LastLatitude = old.Item1, + LastLongitude = old.Item2, + LastGPSPos = old.Item3 } }; this.Type = Typ.Data; diff --git a/Lora-Bot/Models/Packet.cs b/Lora-Bot/Models/Packet.cs index 215b893..a1fd946 100644 --- a/Lora-Bot/Models/Packet.cs +++ b/Lora-Bot/Models/Packet.cs @@ -5,7 +5,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class Packet { - protected void SetLoraData(RecievedData e, TrackerUpdateEvent data) { + protected void SetLoraData(RecievedData e, TrackerUpdateEvent tracker) { /*if(e is Ic800ALoraClientEvent) { Ic800ALoraClientEvent ic = e as Ic800ALoraClientEvent; this.Bandwidth = ic.Bandwidth; @@ -23,12 +23,12 @@ protected void SetLoraData(RecievedData e, TrackerUpdateEvent data) { }*/ if(e is DragionoRecievedObj) { DragionoRecievedObj dragino = e as DragionoRecievedObj; - data.Freqerror = dragino.FreqError; + tracker.Freqerror = dragino.FreqError; } - data.Rssi = e.Rssi; - data.Snr = e.Snr; - data.Crcstatus = e.Crc ? "Ok" : "Bad"; - data.Receivedtime = e.RecievedTime; + tracker.Rssi = e.Rssi; + tracker.Snr = e.Snr; + tracker.Crcstatus = e.Crc ? "Ok" : "Bad"; + tracker.Receivedtime = e.RecievedTime; } } } diff --git a/Lora-Bot/Models/Tracker.cs b/Lora-Bot/Models/Tracker.cs index c455414..6fc1279 100644 --- a/Lora-Bot/Models/Tracker.cs +++ b/Lora-Bot/Models/Tracker.cs @@ -5,8 +5,8 @@ using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { - public class Tracker { - /*private enum ParseType { + /*public class Tracker { + private enum ParseType { Update, Panic } @@ -16,9 +16,9 @@ public class Tracker { public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); public event UpdateDataEvent DataUpdate; public event UpdatePanicEvent PanicUpdate; - public event UpdateStatusEvent StatusUpdate;*/ + public event UpdateStatusEvent StatusUpdate; - /*public Int32 Bandwidth { + public Int32 Bandwidth { get; private set; } public Double BatteryLevel { @@ -101,10 +101,10 @@ public enum Status { Shutdown } - public Tracker() => this.Gps = new GpsInfo();*/ + public Tracker() => this.Gps = new GpsInfo(); #region Private Parsers and Helpers - /*private void Parse(Byte[] data, ParseType dataType) { + private void Parse(Byte[] data, ParseType dataType) { if(data.Length == 21) { this.Name = GetName(data); Single lat = BitConverter.ToSingle(data, 3); @@ -213,11 +213,11 @@ public void SetPanics(LoraClientEvent e, Byte[] data) { public void SetStatus(LoraClientEvent e, String textStatus) { this.SetUpdate(e); this.ParseStatus(textStatus); - }*/ + } #endregion #region Static Functions - /*public static Boolean CheckPacket(String message) { + public static Boolean CheckPacket(String message) { String[] m; if(message.Contains("\r\n")) { m = message.Split(new String[] { "\r\n" }, StringSplitOptions.None); @@ -253,7 +253,7 @@ public static String GetName(Byte[] data) { return ret[1] == 0 ? System.Text.Encoding.ASCII.GetString(new Byte[] { ret[0] }).Trim() : System.Text.Encoding.ASCII.GetString(ret).Trim(); } return ""; - }*/ + } #endregion - } + }*/ } diff --git a/Lora-Bot/Moduls/Mqtt.cs b/Lora-Bot/Moduls/Mqtt.cs index 7c6338f..2ab4d7e 100644 --- a/Lora-Bot/Moduls/Mqtt.cs +++ b/Lora-Bot/Moduls/Mqtt.cs @@ -1,16 +1,18 @@ using System; + using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots.Events; using BlubbFish.Utils.IoT.Bots.Moduls; using BlubbFish.Utils.IoT.Connector; using BlubbFish.Utils.IoT.Interfaces; -using Fraunhofer.Fit.Iot.Lora; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls { - /*class Mqtt : Mqtt { + class Mqtt : Mqtt { public override event ModulEvent Update; - public Mqtt(LoraController lib, InIReader settings) : base(lib, settings) { } + public Mqtt(LoraParser lib, InIReader settings) : base(lib, settings) { } public override void EventLibSetter() { this.library.DataUpdate += this.HandleLibUpdate; @@ -31,5 +33,5 @@ protected override void LibUpadteThread(Object state) { Helper.WriteError("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls.Mqtt.LibUpadteThread: " + e.Message); } } - }*/ + } } diff --git a/Lora-Bot/Moduls/Txtout.cs b/Lora-Bot/Moduls/Txtout.cs index e8b8b1a..a2166db 100644 --- a/Lora-Bot/Moduls/Txtout.cs +++ b/Lora-Bot/Moduls/Txtout.cs @@ -1,20 +1,21 @@ using System; using System.IO; + using BlubbFish.Utils; using BlubbFish.Utils.IoT.Bots.Events; using BlubbFish.Utils.IoT.Bots.Moduls; -using Fraunhofer.Fit.Iot.Lora; -//using Fraunhofer.Fit.Iot.Lora.Trackers; -using Fraunhofer.Fit.Iot.Lora.Events; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls { - /*public class Txtout : AModul { + public class Txtout : AModul { public override event ModulEvent Update; private readonly String filename; private readonly StreamWriter file; - public Txtout(LoraController lib, InIReader settings) : base(lib, settings) { + public Txtout(LoraParser lib, InIReader settings) : base(lib, settings) { if (this.config.ContainsKey("general") && this.config["general"].ContainsKey("path")) { this.filename = this.config["general"]["path"]; this.file = new StreamWriter(this.filename, true); @@ -43,5 +44,5 @@ public override void Dispose() { } protected override void UpdateConfig() {} - }*/ + } } \ No newline at end of file diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 0a5a52a..2c8079b 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -1,14 +1,20 @@ using System; +using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using BlubbFish.Utils; + using Fraunhofer.Fit.Iot.Lora.Events; using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; using Fraunhofer.Fit.IoT.Bots.LoraBot.Models; namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Parser { public class LoraParser { + private readonly SortedDictionary> oldmarkerpos = new SortedDictionary>(); + private readonly Object oldmarkerposlock = new Object(); + public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); @@ -35,31 +41,36 @@ public enum Typ { private async void StatusUpdates(Object sender, StatusUpdateEvent e) => await Task.Run(() => this.StatusUpdate?.Invoke(sender, e)); - internal void ReceivedPacket(Object sender, RecievedData e) { - if(e.Data.Length == 21 && e.Data[0] == 'b' || e.Data[0] == 'p') { - //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### - BinaryPacket p = this.ParseBinaryPacket(e.Data, e); - if(p.Type == BinaryPacket.Typ.Data) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); - this.DataUpdates(sender, p.Data); - } else if(p.Type == BinaryPacket.Typ.Panic) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); - this.PanicUpdates(sender, p.Panic); - } else { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| CRC:" + e.Crc); - } - } else if(e.Data.Length > 3 && e.Data[0] == 'd' && e.Data[1] == 'e' && e.Data[2] == 'b') { - //###### Debug Packet, three lines ############# - DebugPacket p = this.ParseDebugPacket(e.Data, e); - if(p.Type == DebugPacket.Typ.Status) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Status |" + this.ToStringFilter(p.Text) + "| RSSI:" + e.Rssi + " SNR:" + e.Snr); - this.StatusUpdates(sender, p.Status); + public void ReceivedPacket(Object sender, RecievedData data) { + try { + + if(data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { + //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### + BinaryPacket p = this.ParseBinaryPacket(data.Data, data); + if(p.Type == BinaryPacket.Typ.Data) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + this.DataUpdates(sender, p.Data); + } else if(p.Type == BinaryPacket.Typ.Panic) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + this.PanicUpdates(sender, p.Panic); + } else { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| CRC:" + data.Crc); + } + } else if(data.Data.Length > 3 && data.Data[0] == 'd' && data.Data[1] == 'e' && data.Data[2] == 'b') { + //###### Debug Packet, three lines ############# + DebugPacket p = this.ParseDebugPacket(data.Data, data); + if(p.Type == DebugPacket.Typ.Status) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Status |" + this.ToStringFilter(p.Text) + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + this.StatusUpdates(sender, p.Status); + } else { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Debug-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| CRC:" + data.Crc); + } } else { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Debug-Packet not Match! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| CRC:" + e.Crc); + //###### Every else Packet ############# + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Some other Packet! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| '" + this.ToStringFilter(data.Data) + "' RSSI:" + data.Rssi + " SNR:" + data.Snr); } - } else { - //###### Every else Packet ############# - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Some other Packet! [" + e.Data.Length + "]|" + BitConverter.ToString(e.Data).Replace("-", " ") + "| '" + this.ToStringFilter(e.Data) + "' RSSI:" + e.Rssi + " SNR:" + e.Snr); + } catch(Exception e) { + Helper.WriteError("Something Went wrong while Parsing " + e.Message + "\n" + e.StackTrace); } } @@ -121,7 +132,22 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; DateTime date = DateTime.TryParse(data[17].ToString().PadLeft(2, '0') + "." + data[18].ToString().PadLeft(2, '0') + "." + ((UInt16)(data[19] + 2000)).ToString().PadLeft(4, '0') + " " + data[14].ToString().PadLeft(2, '0') + ":" + data[15].ToString().PadLeft(2, '0') + ":" + data[16].ToString().PadLeft(2, '0'), out DateTime dv) ? dv : DateTime.MinValue; Single battery = ((Single)data[20] + 230) / 100; - return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata); + Tuple old = new Tuple(0, 0, DateTime.MinValue); + if(lat != 0 || lon != 0) { + lock(this.oldmarkerposlock) { + if(this.oldmarkerpos.ContainsKey(name)) { + this.oldmarkerpos[name] = new Tuple(lat, lon, DateTime.Now); + } else { + this.oldmarkerpos.Add(name, new Tuple(lat, lon, DateTime.Now)); + } + } + } + lock(this.oldmarkerpos) { + if(this.oldmarkerpos.ContainsKey(name)) { + old = this.oldmarkerpos[name]; + } + } + return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); } } } From 60b8ec420d9acd241a29332a98134cd3739a6796 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Tue, 24 Dec 2019 12:47:23 +0100 Subject: [PATCH 08/29] Parse the correct packet now --- Lora-Bot/Events/TrackerUpdateEvent.cs | 50 +++++++++++++++++---------- Lora-Bot/Models/Packet.cs | 33 +++++++++--------- 2 files changed, 48 insertions(+), 35 deletions(-) diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs index 954c84f..56e470c 100644 --- a/Lora-Bot/Events/TrackerUpdateEvent.cs +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -10,6 +10,8 @@ public String Name { public Double BatteryLevel { get; set; } + + public String Host => Environment.MachineName; #endregion #region Global Lora Data @@ -40,37 +42,47 @@ public Double Freqerror { } #endregion - public Byte Recieverradio { - get; private set; - } - public Byte Recieverinterface { - get; private set; - } - public UInt32 Frequency { - get; private set; - } + #region Ic880a Special Data public Int32 Bandwidth { - get; private set; + get; set; } + + public UInt16 Calculatedcrc { + get; set; + } + public Byte Codingrate { - get; private set; + get; set; } - public Byte Spreadingfactor { - get; private set; + + public UInt32 Frequency { + get; set; } - public UInt16 Calculatedcrc { - get; private set; + + public Byte Recieverinterface { + get; set; + } + + public Byte Recieverradio { + get; set; } + public Double Snrmax { - get; private set; + get; set; } + public Double Snrmin { - get; private set; + get; set; + } + + public Byte Spreadingfactor { + get; set; } + public UInt32 Time { - get; private set; + get; set; } - public String Host => Environment.MachineName; + #endregion public override String MqttTopic() => base.MqttTopic() + this.Name; diff --git a/Lora-Bot/Models/Packet.cs b/Lora-Bot/Models/Packet.cs index a1fd946..3ac8119 100644 --- a/Lora-Bot/Models/Packet.cs +++ b/Lora-Bot/Models/Packet.cs @@ -6,28 +6,29 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class Packet { protected void SetLoraData(RecievedData e, TrackerUpdateEvent tracker) { - /*if(e is Ic800ALoraClientEvent) { - Ic800ALoraClientEvent ic = e as Ic800ALoraClientEvent; - this.Bandwidth = ic.Bandwidth; - this.CalculatedCRC = ic.Calculatedcrc; - this.CodingRate = ic.CodingRate; - this.CRCStatus = ic.CrcStatus; - this.Frequency = ic.Frequency; - this.RecieverInterface = ic.Interface; - this.Modulation = ic.Modulation; - this.RecieverRadio = ic.Radio; - this.SnrMax = ic.SnrMax; - this.SnrMin = ic.SnrMin; - this.SpreadingFactor = ic.Spreadingfactor; - this.Time = ic.Time; - }*/ + if(e is Ic880aRecievedObj) { + Ic880aRecievedObj ic = e as Ic880aRecievedObj; + tracker.Bandwidth = ic.Bandwidth; + tracker.Calculatedcrc = ic.Calculatedcrc; + tracker.Codingrate = ic.CodingRate; + tracker.Crcstatus = ic.CrcStatus; + tracker.Frequency = ic.Frequency; + tracker.Recieverinterface = ic.Interface; + //tracker.Modulation = ic.Modulation; + tracker.Recieverradio = ic.Radio; + tracker.Snrmax = ic.SnrMax; + tracker.Snrmin = ic.SnrMin; + tracker.Spreadingfactor = ic.Spreadingfactor; + tracker.Time = ic.Time; + } if(e is DragionoRecievedObj) { DragionoRecievedObj dragino = e as DragionoRecievedObj; tracker.Freqerror = dragino.FreqError; + tracker.Crcstatus = e.Crc ? "Ok" : "Bad"; } tracker.Rssi = e.Rssi; tracker.Snr = e.Snr; - tracker.Crcstatus = e.Crc ? "Ok" : "Bad"; + tracker.Receivedtime = e.RecievedTime; } } From 6b25d2dffb96e996f477a1cd106e3e6114dd3829 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Mon, 6 Jan 2020 15:22:13 +0100 Subject: [PATCH 09/29] documenting Crypto... :) --- Lora-Bot/Lora-Bot.csproj | 4 ++++ doc/format.md | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 doc/format.md diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index 50e7e5b..af40831 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -45,6 +45,10 @@ + + + + diff --git a/doc/format.md b/doc/format.md new file mode 100644 index 0000000..2cdb5b8 --- /dev/null +++ b/doc/format.md @@ -0,0 +1,40 @@ +# Binary Format +The data that goes through the air is a binary transmission with the length of 18 Byte. +It contains two parts, a unique counter and the encrypted content. +```elm +schema message { + counter : uint16_t; + data : uint8_t[16]; +} +``` +You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be +known to both sides of the communication. Here we assume `key = 0xDEADBEEF; counter = 0x0001`. +This both will be summated together and generate a sha2 `crypto = sha2(key + counter);`. + +Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. +We CUT crypto to the length of data. + +```elm +schema data { + name : uint16_t; // [0..1] + lan : float; // [2..5] + lon : float; // [6..9] + height : uint16_t; // [10..11] + battery : uint8_t; // [12] + hdop : uint8_t; // [13] + status : bitfield : uint8_t { // [14] + has_time : 1; // 0 = true, 1 = false + has_date : 1; // 0 = true, 1 = false + has_fix : 1; // 0 = true, 1 = false + satelites : 5; // uint5_t + } + counter_crc: uint8_t; // [15] +} +``` +As Example: +`crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7` +```elm +dataraw { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11101100,0x97 } +``` +`dataraw = 0x4141004352050012980604D2785AEC97` +`data = 0xE6221A818DC90C0771267DAEF67F3E70` \ No newline at end of file From 7bc69a3ca4b1dd0bb0b4de3c23bf7487fd1df284 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Mon, 6 Jan 2020 23:52:36 +0100 Subject: [PATCH 10/29] Docu... --- doc/format.md | 49 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 42 insertions(+), 7 deletions(-) diff --git a/doc/format.md b/doc/format.md index 2cdb5b8..65c9d21 100644 --- a/doc/format.md +++ b/doc/format.md @@ -1,6 +1,7 @@ # Binary Format The data that goes through the air is a binary transmission with the length of 18 Byte. It contains two parts, a unique counter and the encrypted content. +## General Format ```elm schema message { counter : uint16_t; @@ -8,12 +9,13 @@ schema message { } ``` You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be -known to both sides of the communication. Here we assume `key = 0xDEADBEEF; counter = 0x0001`. -This both will be summated together and generate a sha2 `crypto = sha2(key + counter);`. +known to both sides of the communication. This both will be summated together and generate a +sha2 `crypto = sha2(key + counter);`. Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. We CUT crypto to the length of data. +## Data Section ```elm schema data { name : uint16_t; // [0..1] @@ -31,10 +33,43 @@ schema data { counter_crc: uint8_t; // [15] } ``` -As Example: -`crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7` +## Examples +We calculate a crypto and recovery it. + +### Encryption +#### Increment Counter +```elm +counter = 0x0001; +``` +#### Calculate xorkey ```elm -dataraw { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11101100,0x97 } +key = 0xDEADBEEF; +shakey = sha256(key + counter); +crypto = ToInt128(shakey); //Only use the last 128 bit of shakey +crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7; ``` -`dataraw = 0x4141004352050012980604D2785AEC97` -`data = 0xE6221A818DC90C0771267DAEF67F3E70` \ No newline at end of file +#### Create Datablock +```elm +data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11101100,0x97 } +data = 0x4141004352050012980604D2785AEC97; +``` +#### Calculate message +```elm +datac = data ^ crypto; +message = counter<<128 | datac; +message = 0x0001E6221A818DC90C0771267DAEF67F3E70; +``` + +### Decryption +#### Reading counter +```elm +message = counter>>128; +counter = 0x0001; +``` +#### Calculating xorkey +```elm +key = 0xDEADBEEF; +shakey = sha256(key + counter); +crypto = ToInt128(shakey); //Only use the last 128 bit of shakey +crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7; +``` \ No newline at end of file From 8147e801cc1011e83901fc426372774f78c4c5ec Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Tue, 7 Jan 2020 10:53:59 +0100 Subject: [PATCH 11/29] Describe the format for the binary lora transmission --- Lora-Bot/Lora-Bot.csproj | 2 +- doc/Binaryformat.md | 89 ++++++++++++++++++++++++++++++++++++++++ doc/format.md | 75 --------------------------------- 3 files changed, 90 insertions(+), 76 deletions(-) create mode 100644 doc/Binaryformat.md delete mode 100644 doc/format.md diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index af40831..e28c787 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -46,7 +46,7 @@ - + diff --git a/doc/Binaryformat.md b/doc/Binaryformat.md new file mode 100644 index 0000000..f413195 --- /dev/null +++ b/doc/Binaryformat.md @@ -0,0 +1,89 @@ +# Binary Format +The data that goes through the air is a binary transmission with the length of 18 Byte. +It contains two parts, a unique counter and the encrypted content. +## General Format +```elm +schema message { + counter : uint16_t; + data : uint8_t[16]; +} +``` +You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be +known to both sides of the communication. This both will be summated together and generate a +sha2 `crypto = sha2(key + counter);`. + +Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. +We CUT crypto to the length of data. + +## Data Section +```elm +schema data { + name : uint16_t; // [0..1] + lan : float; // [2..5] + lon : float; // [6..9] + height : uint16_t; // [10..11] + battery : uint8_t; // [12] + hdop : uint8_t; // [13] + status : bitfield : uint8_t { // [14] + message_type : 1 // 0 = regular, 1 = eventbased + has_time : 1; // 0 = true, 1 = false + has_date : 1; // 0 = true, 1 = false + has_fix : 1; // 0 = true, 1 = false + satelites : 4; // uint5_t + } + counter_crc: uint8_t; // [15] +} +``` +## Examples +We calculate a crypto and recovery it. For this example we use `key = 0xDEADBEEF;`. +So this is now a very bad key. + +### Encryption +#### Increment Counter +```elm +counter = 0x0001; +``` +#### Calculate xorkey +```elm +key = 0xDEADBEEF; +shakey = sha256(key + counter); +crypto = shakey & 00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; +crypro = 0xA7631AC2DFCC0C15E920797C8E25D2E7; +``` +#### Create Datablock +```elm +data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11111100,0x97 } +data = 0x4141004352050012980604D2785AFC97; +``` +#### Calculate message +```elm +datac = data ^ crypto; +message = counter << 128 | datac; +message = 0x0001E6221A818DC90C0771267DAEF67F2E70; +``` + +### Decryption +We get `message = 0x0001E6221A818DC90C0771267DAEF67F2E70;` as message. +#### Reading counter +```elm +counter = message >> 128; +counter = 0x0001; +``` +#### Calculating xorkey +```elm +key = 0xDEADBEEF; +shakey = sha256(key + counter); +crypto = shakey & 00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; +crypro = 0xA7631AC2DFCC0C15E920797C8E25D2E7; +``` +### Decrypting Message +```elm +datac = message & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; +datac = 0xE6221A818DC90C0771267DAEF67F2E70; +data = datac ^ crypto; +data = 0x4141004352050012980604D2785AFC97; +``` +#### Decode Datablock +```elm +data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11111100,0x97 } +``` \ No newline at end of file diff --git a/doc/format.md b/doc/format.md deleted file mode 100644 index 65c9d21..0000000 --- a/doc/format.md +++ /dev/null @@ -1,75 +0,0 @@ -# Binary Format -The data that goes through the air is a binary transmission with the length of 18 Byte. -It contains two parts, a unique counter and the encrypted content. -## General Format -```elm -schema message { - counter : uint16_t; - data : uint8_t[16]; -} -``` -You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be -known to both sides of the communication. This both will be summated together and generate a -sha2 `crypto = sha2(key + counter);`. - -Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. -We CUT crypto to the length of data. - -## Data Section -```elm -schema data { - name : uint16_t; // [0..1] - lan : float; // [2..5] - lon : float; // [6..9] - height : uint16_t; // [10..11] - battery : uint8_t; // [12] - hdop : uint8_t; // [13] - status : bitfield : uint8_t { // [14] - has_time : 1; // 0 = true, 1 = false - has_date : 1; // 0 = true, 1 = false - has_fix : 1; // 0 = true, 1 = false - satelites : 5; // uint5_t - } - counter_crc: uint8_t; // [15] -} -``` -## Examples -We calculate a crypto and recovery it. - -### Encryption -#### Increment Counter -```elm -counter = 0x0001; -``` -#### Calculate xorkey -```elm -key = 0xDEADBEEF; -shakey = sha256(key + counter); -crypto = ToInt128(shakey); //Only use the last 128 bit of shakey -crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7; -``` -#### Create Datablock -```elm -data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11101100,0x97 } -data = 0x4141004352050012980604D2785AEC97; -``` -#### Calculate message -```elm -datac = data ^ crypto; -message = counter<<128 | datac; -message = 0x0001E6221A818DC90C0771267DAEF67F3E70; -``` - -### Decryption -#### Reading counter -```elm -message = counter>>128; -counter = 0x0001; -``` -#### Calculating xorkey -```elm -key = 0xDEADBEEF; -shakey = sha256(key + counter); -crypto = ToInt128(shakey); //Only use the last 128 bit of shakey -crypro = 0xa7631ac2dfcc0c15e920797c8e25d2e7; -``` \ No newline at end of file From 2784b1faed8141fb3b6aab427fdf8b27f122552f Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Wed, 8 Jan 2020 16:05:31 +0100 Subject: [PATCH 12/29] updatet settings --- Lora-Bot/config-example/settings.conf.example | 87 +++++++++---------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 36b4ffd..588574a 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -19,50 +19,43 @@ path=/var/log/lorabot.log ;power=17 ;gain=0 - - -[lora] -type=Ic880alora -pin_sspin=Pin10 -pin_rst=Pin21 -spichan=Channel0 -; Set Basic Frequencies -frequency0=867125000 -frequency1=868125000 -; Set Per Virtual Interface IF0-7 (Freq means the offset to the basic frequency) -interface0enable=true -interface0chain=0 -interface0frequency=-375000 -interface1enable=true -interface1chain=0 -interface1frequency=-125000 -interface2enable=true -interface2chain=0 -interface2frequency=125000 -interface3enable=true -interface3chain=0 -interface3frequency=375000 -interface4enable=true -interface4chain=1 -interface4frequency=-375000 -interface5enable=true -interface5chain=1 -interface5frequency=-125000 -interface6enable=true -interface6chain=1 -interface6frequency=125000 -interface7enable=true -interface7chain=1 -interface7frequency=375000 -; Virtual Interface IF8 Lora Interface -interface8enable=false -interface8chain=1 -interface8frequency=-200000 -lorabandwith=250000 -loraspreadingfactor=7 -; Virtual Interface IF9 FSK Interface -interface9enable=false -interface9chain=1 -interface9frequency=300000 -fskbandwith=125000 -fskdatarate=50000 +;[lora] +;debug=true +;type=Ic880a +;pin_sspin=Pin10 +;pin_rst=Pin21 +;spichan=Channel0 +; ## Set Basic Frequencies ## +;frequency0=867125000 +;frequency1=868125000 +; ## Set Per Virtual Interface IF0-7 (Freq means the offset to the basic frequency) ## +;interface0frequency=-375000 +;interface0chain=0 +;interface1frequency=-125000 +;interface1chain=0 +;interface2frequency=125000 +;interface2chain=0 +;interface3frequency=375000 +;interface3chain=0 +;interface4frequency=-375000 +;interface4chain=1 +;interface5frequency=-125000 +;interface5chain=1 +;interface6frequency=125000 +;interface6chain=1 +;interface7frequency=375000 +;interface7chain=1 +; ## Virtual Interface IF8 Lora Interface ## +;interface8frequency=-200000 +;interface8chain=1 +;lorabandwith=250000 +;loraspreadingfactor=7 +; ## Virtual Interface IF9 FSK Interface ## +;interface9frequency=300000 +;interface9chain=1 +;fskbandwith=125000 +;fskdatarate=50000 +; ## General Settings ## +;crc=true +;lorawan=false +;lbt_enable=false From 8cb6e6ee22359f03c4c96bc08058043cf314509c Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Wed, 8 Jan 2020 22:43:05 +0100 Subject: [PATCH 13/29] testing... --- Lora-Bot/config-example/settings.conf.example | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 588574a..6ac852a 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -22,12 +22,14 @@ path=/var/log/lorabot.log ;[lora] ;debug=true ;type=Ic880a -;pin_sspin=Pin10 -;pin_rst=Pin21 +;pin_sspin=8 +;pin_rst=5 ;spichan=Channel0 ; ## Set Basic Frequencies ## ;frequency0=867125000 +;radio0tx=true ;frequency1=868125000 +;radio1tx=true ; ## Set Per Virtual Interface IF0-7 (Freq means the offset to the basic frequency) ## ;interface0frequency=-375000 ;interface0chain=0 From 50c4c48292df039f51d9f39c53c03022db3d1c4a Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Fri, 10 Jan 2020 23:41:59 +0100 Subject: [PATCH 14/29] Updated config --- Lora-Bot/config-example/settings.conf.example | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 6ac852a..75fdfb2 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -27,9 +27,7 @@ path=/var/log/lorabot.log ;spichan=Channel0 ; ## Set Basic Frequencies ## ;frequency0=867125000 -;radio0tx=true ;frequency1=868125000 -;radio1tx=true ; ## Set Per Virtual Interface IF0-7 (Freq means the offset to the basic frequency) ## ;interface0frequency=-375000 ;interface0chain=0 @@ -38,7 +36,7 @@ path=/var/log/lorabot.log ;interface2frequency=125000 ;interface2chain=0 ;interface3frequency=375000 -;interface3chain=0 +,interface3chain=0 ;interface4frequency=-375000 ;interface4chain=1 ;interface5frequency=-125000 @@ -48,16 +46,20 @@ path=/var/log/lorabot.log ;interface7frequency=375000 ;interface7chain=1 ; ## Virtual Interface IF8 Lora Interface ## -;interface8frequency=-200000 -;interface8chain=1 +;interface8frequency=0 +;interface8chain=0 ;lorabandwith=250000 -;loraspreadingfactor=7 +;loraspreadingfactor=10 ; ## Virtual Interface IF9 FSK Interface ## ;interface9frequency=300000 ;interface9chain=1 ;fskbandwith=125000 ;fskdatarate=50000 ; ## General Settings ## +;sendbw=125000 +;sendsf=10 +;sendcr=7 +;sendpreamble=8 ;crc=true ;lorawan=false ;lbt_enable=false From c776adff6e87778595f8ce28f92a383b4345123c Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 11 Jan 2020 22:40:04 +0100 Subject: [PATCH 15/29] Update Binaryformat Readme --- Lora-Bot/config-example/settings.conf.example | 1 - doc/Binaryformat.md | 72 +++++++++++-------- 2 files changed, 44 insertions(+), 29 deletions(-) diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 75fdfb2..3e09569 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -62,4 +62,3 @@ path=/var/log/lorabot.log ;sendpreamble=8 ;crc=true ;lorawan=false -;lbt_enable=false diff --git a/doc/Binaryformat.md b/doc/Binaryformat.md index f413195..015dba1 100644 --- a/doc/Binaryformat.md +++ b/doc/Binaryformat.md @@ -4,13 +4,14 @@ It contains two parts, a unique counter and the encrypted content. ## General Format ```elm schema message { - counter : uint16_t; - data : uint8_t[16]; + counter : uint16_t; + name : uint16_t; + data : uint8_t[14]; } ``` You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be known to both sides of the communication. This both will be summated together and generate a -sha2 `crypto = sha2(key + counter);`. +sha2 `crypto = sha2(key + counter + name);`. Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. We CUT crypto to the length of data. @@ -18,72 +19,87 @@ We CUT crypto to the length of data. ## Data Section ```elm schema data { - name : uint16_t; // [0..1] - lan : float; // [2..5] - lon : float; // [6..9] - height : uint16_t; // [10..11] - battery : uint8_t; // [12] - hdop : uint8_t; // [13] - status : bitfield : uint8_t { // [14] + lan : float; // [0..3] + lon : float; // [4..7] + height : uint16_t; // [8..9] + battery : uint8_t; // [10] + hdop : uint8_t; // [11] + status : bitfield : uint8_t { // [12] message_type : 1 // 0 = regular, 1 = eventbased has_time : 1; // 0 = true, 1 = false has_date : 1; // 0 = true, 1 = false has_fix : 1; // 0 = true, 1 = false satelites : 4; // uint5_t } - counter_crc: uint8_t; // [15] + counter_name_crc: uint8_t; // [13] } ``` +* lan: Latitude coded as 4 Byte value. +* lon: Longitude coded as 4 Byte value. +* height: Height * 10; coded as 2 Byte value (so resolution is 10 cm). +* battery: (Battery_Voltage * 100)-230; coded as 1 Byte (so resolution is 0.01V from 2.3V to 4.85V, fits for one LiPo Cell). +* hdop: Hdop * 10; coded as 1 Byte (so resolution is 0.1, reach from 0.0 to 25.5). +* message_type: If the message was send regular, like to faar distance or timebased use 0, if it was userintended like pressing a button use 1 (it will be handled as "panic" message). +* has_time: If the gps module provides a valid timestamp. +* has_date: If the gps module provides a valid date. +* has_fix: If the gps module say there is a gps fix. +* satelites: How many satelites the gps module see (reach from 0 to 15). +* coounter_name_crc: calculate a CRC8 value above the first 4 Byte (counter, name) of the complete packet, so you can maybe see if it was manipulated. ## Examples We calculate a crypto and recovery it. For this example we use `key = 0xDEADBEEF;`. So this is now a very bad key. ### Encryption -#### Increment Counter +#### Using counter and name ```elm counter = 0x0001; +name = 0x4141; ``` #### Calculate xorkey ```elm key = 0xDEADBEEF; -shakey = sha256(key + counter); -crypto = shakey & 00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0xA7631AC2DFCC0C15E920797C8E25D2E7; +shakey = sha256(key + counter + name); +crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; +crypro = 0x4B2438D2FC98588CE47FD29E8E7D; ``` #### Create Datablock ```elm -data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11111100,0x97 } -data = 0x4141004352050012980604D2785AFC97; +data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x48 } +data = 0x004352050012980604D2785AFC48; ``` #### Calculate message ```elm datac = data ^ crypto; -message = counter << 128 | datac; -message = 0x0001E6221A818DC90C0771267DAEF67F2E70; +datac = 0x4B676AD7FC8AC08AE0ADAAC47235; +message = counter << 128 | name<<112 | datac; +message = 0x000141414B676AD7FC8AC08AE0ADAAC47235; ``` ### Decryption -We get `message = 0x0001E6221A818DC90C0771267DAEF67F2E70;` as message. -#### Reading counter +We get `message = 0x000141414B676AD7FC8AC08AE0ADAAC47235;` as message. +#### Reading counter and name ```elm counter = message >> 128; counter = 0x0001; +name = message >> 112; +name = name & 0x0000FFFF; +name = 0x4141; ``` #### Calculating xorkey ```elm key = 0xDEADBEEF; -shakey = sha256(key + counter); -crypto = shakey & 00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0xA7631AC2DFCC0C15E920797C8E25D2E7; +shakey = sha256(key + counter + name); +crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; +crypro = 0x4B2438D2FC98588CE47FD29E8E7D; ``` ### Decrypting Message ```elm -datac = message & 0x0000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; -datac = 0xE6221A818DC90C0771267DAEF67F2E70; +datac = message & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; +datac = 0x4B676AD7FC8AC08AE0ADAAC47235; data = datac ^ crypto; -data = 0x4141004352050012980604D2785AFC97; +data = 0x004352050012980604D2785AFC48; ``` #### Decode Datablock ```elm -data { 'A','A',55.234,6.9812,123.4,3.5,0.9,0b11111100,0x97 } +data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x48 } ``` \ No newline at end of file From 84c8c2c2aa2c0dd701fa467b02e31a41c06b424b Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 11 Jan 2020 23:37:27 +0100 Subject: [PATCH 16/29] Start Implementing decodefunction --- Lora-Bot/Lora-Bot.csproj | 1 + Lora-Bot/Parser/LoraParser.cs | 24 + doc/Mqttformat.md | 1858 +++++++++++++++++++++++++++++++++ 3 files changed, 1883 insertions(+) create mode 100644 doc/Mqttformat.md diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index e28c787..6f0cb4d 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -47,6 +47,7 @@ + diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 2c8079b..156f285 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; @@ -149,5 +150,28 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { } return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); } + + Byte[] key = new Byte[] { 0xDE, 0xAD, 0xBE, 0xEF }; + + private Byte[] DecodeData(Byte[] encoded) { + if(encoded.Length != 18) { + return encoded; + } + Byte[] decoded = new Byte[encoded.Length]; + Byte[] binkey = new Byte[this.key.Length + 4]; + for(Byte i = 0; i < 4; i++) { + binkey[i] = encoded[i]; + decoded[i] = encoded[i]; + } + for(Int32 i = 0; i < this.key.Length; i++) { + binkey[i + 4] = this.key[i]; + } + SHA256 sha256Hash = SHA256.Create(); + Byte[] crypto = sha256Hash.ComputeHash(binkey); + for(Int32 i = 0; i < encoded.Length-4; i++) { + decoded[i + 4] = (Byte)(encoded[i + 4] ^ crypto[crypto.Length - 1 - encoded.Length - 5 + i]); + } + return decoded; + } } } diff --git a/doc/Mqttformat.md b/doc/Mqttformat.md new file mode 100644 index 0000000..a4aade2 --- /dev/null +++ b/doc/Mqttformat.md @@ -0,0 +1,1858 @@ +# Lora-Internal-Flow 1.0.0 documentation + + + +Internal Communication for: +* Lora-Gateway +* Lora-Map + + +## Table of Contents + + + +* [Servers](#servers) + + +* [Channels](#channels) + + + + + + +## Servers + + + + + + + + + + + + + + + + + + + + + + +
URLProtocolDescription
127.0.0.1:{port}mqttLora-Broker
+
+ URL Variables + + + + + + + + + + + + + + + + + +
NameDefault valuePossible valuesDescription
port + 1883 + +
  • 1883
  • 8883
+
Secure connection (TLS) is available through port 8883.
+
+
+
+ Security Requirements + + + + + + + + + + + + + + + + + + + +
TypeInNameSchemeFormatDescription
userPassword

Using Username and Password to connect to online broker

+
+
+
+ + + + + + +## Channels + + + + + + +Topic witch contains the tracking data. + + + + +#### Channel Parameters + + + +##### deviceID + + +The ID of the streetlight. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
deviceID + + stringAny
+ + + + + +### `subscribe` lora/data/{deviceID} + +#### Message + + + +Informs you about a Position and Status of a Tracker + + + + + + + +##### Payload + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
Bandwidth + + integer

Bandwidth on witch the Signal was recieved

+
Any
BatteryLevel + + number

Voltage of the battery from the device

+
Any
Calculatedcrc + + integer

The calculated CRC

+
Any
Codingrate + + integer

The Codingrate in witch the Signal was recieved

+
Any
Crcstatus + + string

Shows the CRC-Status in a Field

+
Ok, Bad, No
Frequency + + integer

The Frequency on that the Message was arrived

+
Any
Gps + + object

Gps-Data of a Message

+
Any
Gps.Fix + + boolean

Status of the Tracker, true if it has GPS-Signal

+
Any
Gps.Hdop + + number

Dislocation from GPS-Reciever

+
Any
Gps.Height + + number

Height of the GPS-Reciever

+
Any
Gps.LastGPSPos + + string

Timestamp when the GPS-Reciever has its last position

+
Any
Gps.LastLatitude + + number

Last Latitude of the GPS-Reciever

+
Any
Gps.LastLongitude + + number

Last Longitude of the GPS-Reciever

+
Any
Gps.Latitude + + number

Latitude of the GPS-Reciever

+
Any
Gps.Longitude + + number

Longitude of the GPS-Reciever

+
Any
Gps.Time + + string

Timestamp of the GPS-Reciever, that it gets from the Satelites

+
Any
Host + + string

Name of the Gateway that Recieves the Data

+
Any
Name + + string

Name of the GPS-Tracker, must be unique between every Device

+
Any
PacketRssi + + number

Recieve Signal Strength Index for the whole LORA-Messgae

+
Any
Receivedtime + + string

Timestamp of the Gateway, when it recieves the LORA-Message

+
Any
Recieverinterface + + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Recieverradio + + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Rssi + + number

Recieve Signal Strength Index for the LORA-Message

+
Any
Snr + + number

Signal to Noise Ratio of the LORA-Message

+
Any
Snrmax + + number

Maximum Signal to Noise Ratio of the LORA-Message

+
Any
Snrmin + + number

Minimum Signal to Noise Ratio of the LORA-Message

+
Any
Spreadingfactor + + integer

The Spreadingfactor of the LORA-Message

+
Any
Time + + integer

Internal Timecounter of the LORA-Reciever

+
Any
+ + + +###### Example of payload _(generated)_ + +```json +{ + "Bandwidth": 7800, + "BatteryLevel": 2.5, + "Calculatedcrc": 0, + "Codingrate": 5, + "Crcstatus": "Ok", + "Frequency": 0, + "Gps": { + "Fix": true, + "Hdop": 0.8, + "Height": 0, + "LastGPSPos": "01/01/2019 12:00:00", + "LastLatitude": 50.7, + "LastLongitude": 7.2, + "Latitude": 50.7, + "Longitude": 7.2, + "Time": "01/01/2019 12:00:00" + }, + "Host": "string", + "Name": "string", + "PacketRssi": 0, + "Receivedtime": "01/01/2019 12:00:00", + "Recieverinterface": 0, + "Recieverradio": 0, + "Rssi": 0, + "Snr": 0, + "Snrmax": 0, + "Snrmin": 0, + "Spreadingfactor": 7, + "Time": 0 +} +``` + + + + + + + + + + + +Topic witch contains the tracking data, when the panic buttons was pressed + + + + +#### Channel Parameters + + + +##### deviceID + + +The ID of the streetlight. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
deviceID + + stringAny
+ + + + + +### `subscribe` lora/panic/{deviceID} + +#### Message + + + +Informs you about a Position and Status of a Tracker + + + + + + + +##### Payload + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
Bandwidth + + integer

Bandwidth on witch the Signal was recieved

+
Any
BatteryLevel + + number

Voltage of the battery from the device

+
Any
Calculatedcrc + + integer

The calculated CRC

+
Any
Codingrate + + integer

The Codingrate in witch the Signal was recieved

+
Any
Crcstatus + + string

Shows the CRC-Status in a Field

+
Ok, Bad, No
Frequency + + integer

The Frequency on that the Message was arrived

+
Any
Gps + + object

Gps-Data of a Message

+
Any
Gps.Fix + + boolean

Status of the Tracker, true if it has GPS-Signal

+
Any
Gps.Hdop + + number

Dislocation from GPS-Reciever

+
Any
Gps.Height + + number

Height of the GPS-Reciever

+
Any
Gps.LastGPSPos + + string

Timestamp when the GPS-Reciever has its last position

+
Any
Gps.LastLatitude + + number

Last Latitude of the GPS-Reciever

+
Any
Gps.LastLongitude + + number

Last Longitude of the GPS-Reciever

+
Any
Gps.Latitude + + number

Latitude of the GPS-Reciever

+
Any
Gps.Longitude + + number

Longitude of the GPS-Reciever

+
Any
Gps.Time + + string

Timestamp of the GPS-Reciever, that it gets from the Satelites

+
Any
Host + + string

Name of the Gateway that Recieves the Data

+
Any
Name + + string

Name of the GPS-Tracker, must be unique between every Device

+
Any
PacketRssi + + number

Recieve Signal Strength Index for the whole LORA-Messgae

+
Any
Receivedtime + + string

Timestamp of the Gateway, when it recieves the LORA-Message

+
Any
Recieverinterface + + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Recieverradio + + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Rssi + + number

Recieve Signal Strength Index for the LORA-Message

+
Any
Snr + + number

Signal to Noise Ratio of the LORA-Message

+
Any
Snrmax + + number

Maximum Signal to Noise Ratio of the LORA-Message

+
Any
Snrmin + + number

Minimum Signal to Noise Ratio of the LORA-Message

+
Any
Spreadingfactor + + integer

The Spreadingfactor of the LORA-Message

+
Any
Time + + integer

Internal Timecounter of the LORA-Reciever

+
Any
+ + + +###### Example of payload _(generated)_ + +```json +{ + "Bandwidth": 7800, + "BatteryLevel": 2.5, + "Calculatedcrc": 0, + "Codingrate": 5, + "Crcstatus": "Ok", + "Frequency": 0, + "Gps": { + "Fix": true, + "Hdop": 0.8, + "Height": 0, + "LastGPSPos": "01/01/2019 12:00:00", + "LastLatitude": 50.7, + "LastLongitude": 7.2, + "Latitude": 50.7, + "Longitude": 7.2, + "Time": "01/01/2019 12:00:00" + }, + "Host": "string", + "Name": "string", + "PacketRssi": 0, + "Receivedtime": "01/01/2019 12:00:00", + "Recieverinterface": 0, + "Recieverradio": 0, + "Rssi": 0, + "Snr": 0, + "Snrmax": 0, + "Snrmin": 0, + "Spreadingfactor": 7, + "Time": 0 +} +``` + + + + + + + + + + + +Topic witch contains status of the devices + + + + +#### Channel Parameters + + + +##### deviceID + + +The ID of the streetlight. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
deviceID + + stringAny
+ + + + + +### `subscribe` lora/status/{deviceID} + +#### Message + + + +Informs you about a Status of a Tracker + + + + + + + +##### Payload + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionAccepted values
Bandwidth + + integer

Bandwidth on witch the Signal was recieved

+
Any
BatteryLevel + + number

Voltage of the battery from the device

+
Any
Calculatedcrc + + integer

The calculated CRC

+
Any
Codingrate + + integer

The Codingrate in witch the Signal was recieved

+
Any
Crcstatus + + string

Shows the CRC-Status in a Field

+
Ok, Bad, No
DeviceStatus + + string

Shows the internal state in a Field

+
Startup, Powersave, Shutdown
Frequency + + integer

The Frequency on that the Message was arrived

+
Any
FrequencyOffset + + integer

The internal offset to the base frequency, to compensate cheap china rf modules

+
Any
Host + + string

Name of the Gateway that Recieves the Data

+
Any
IpAddress + + string

IP-Address of the device, for debug

+
Any
Name + + string

Name of the GPS-Tracker, must be unique between every Device

+
Any
PacketRssi + + number

Recieve Signal Strength Index for the whole LORA-Messgae

+
Any
Receivedtime + + string

Timestamp of the Gateway, when it recieves the LORA-Message

+
Any
Recieverinterface + + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Recieverradio + + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

+
Any
Rssi + + number

Recieve Signal Strength Index for the LORA-Message

+
Any
Snr + + number

Signal to Noise Ratio of the LORA-Message

+
Any
Snrmax + + number

Maximum Signal to Noise Ratio of the LORA-Message

+
Any
Snrmin + + number

Minimum Signal to Noise Ratio of the LORA-Message

+
Any
Spreadingfactor + + integer

The Spreadingfactor of the LORA-Message

+
Any
Time + + integer

Internal Timecounter of the LORA-Reciever

+
Any
Version + + integer

Software-Versionsnumber of the Device

+
Any
WifiActive + + boolean

Status if the Device successufly connect to a wifi

+
Any
WifiSsid + + string

SSID of the WIFI witch the device connects to.

+
Any
+ + + +###### Example of payload _(generated)_ + +```json +{ + "Bandwidth": 7800, + "BatteryLevel": 2.5, + "Calculatedcrc": 0, + "Codingrate": 5, + "Crcstatus": "Ok", + "DeviceStatus": "Startup", + "Frequency": 0, + "FrequencyOffset": 0, + "Host": "string", + "IpAddress": "0.0.0.0", + "Name": "string", + "PacketRssi": 0, + "Receivedtime": "01/01/2019 12:00:00", + "Recieverinterface": 0, + "Recieverradio": 0, + "Rssi": 0, + "Snr": 0, + "Snrmax": 0, + "Snrmin": 0, + "Spreadingfactor": 7, + "Time": 0, + "Version": 0, + "WifiActive": true, + "WifiSsid": "string" +} +``` + + + + + + + + + + From 11d509a4249dcb57d219ba98ca6b1023dfbb6495 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Tue, 14 Jan 2020 15:17:40 +0100 Subject: [PATCH 17/29] Change sha generation --- doc/Binaryformat.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/Binaryformat.md b/doc/Binaryformat.md index 015dba1..119b704 100644 --- a/doc/Binaryformat.md +++ b/doc/Binaryformat.md @@ -11,7 +11,7 @@ schema message { ``` You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be known to both sides of the communication. This both will be summated together and generate a -sha2 `crypto = sha2(key + counter + name);`. +sha2 `crypto = sha2(key<<32 | name<<16 | counter);`. Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. We CUT crypto to the length of data. @@ -57,10 +57,10 @@ name = 0x4141; ``` #### Calculate xorkey ```elm -key = 0xDEADBEEF; -shakey = sha256(key + counter + name); +key = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF; +shakey = sha256(key << 32 | name << 16 | counter); crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0x4B2438D2FC98588CE47FD29E8E7D; +crypro = 0x43557371C5CB113D83B20E337301; ``` #### Create Datablock ```elm @@ -70,13 +70,13 @@ data = 0x004352050012980604D2785AFC48; #### Calculate message ```elm datac = data ^ crypto; -datac = 0x4B676AD7FC8AC08AE0ADAAC47235; +datac = 0x43162174C5D9893B876076698F49; message = counter << 128 | name<<112 | datac; -message = 0x000141414B676AD7FC8AC08AE0ADAAC47235; +message = 0x0001414143162174C5D9893B876076698F49; ``` ### Decryption -We get `message = 0x000141414B676AD7FC8AC08AE0ADAAC47235;` as message. +We get `message = 0x0001414143162174C5D9893B876076698F49;` as message. #### Reading counter and name ```elm counter = message >> 128; @@ -87,15 +87,15 @@ name = 0x4141; ``` #### Calculating xorkey ```elm -key = 0xDEADBEEF; -shakey = sha256(key + counter + name); +key = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF; +shakey = sha256(key << 32 | name << 16 | counter); crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0x4B2438D2FC98588CE47FD29E8E7D; +crypro = 0x43557371C5CB113D83B20E337301; ``` ### Decrypting Message ```elm datac = message & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -datac = 0x4B676AD7FC8AC08AE0ADAAC47235; +datac = 0x43162174C5D9893B876076698F49; data = datac ^ crypto; data = 0x004352050012980604D2785AFC48; ``` From 90c18fbf9caad450285dfc1af8c8280423da9df7 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Wed, 15 Jan 2020 15:02:25 +0100 Subject: [PATCH 18/29] woring on Crypto --- Lora-Bot/Parser/LoraParser.cs | 39 +++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 156f285..898a2c3 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -44,8 +44,11 @@ public enum Typ { public void ReceivedPacket(Object sender, RecievedData data) { try { - - if(data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { + if (data.Data.Length == 18) { + Byte[] decoded = this.DecodeData(data.Data); + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + decoded.Length + "]|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + } + if (data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### BinaryPacket p = this.ParseBinaryPacket(data.Data, data); if(p.Type == BinaryPacket.Typ.Data) { @@ -151,26 +154,36 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); } - Byte[] key = new Byte[] { 0xDE, 0xAD, 0xBE, 0xEF }; + Byte[] key = new Byte[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF }; private Byte[] DecodeData(Byte[] encoded) { - if(encoded.Length != 18) { + Console.WriteLine("En: " + BitConverter.ToString(encoded).Replace("-", " ")); + Byte[] decoded = new Byte[encoded.Length]; + if (encoded.Length != 18) { return encoded; } - Byte[] decoded = new Byte[encoded.Length]; + Byte[] binkey = new Byte[this.key.Length + 4]; - for(Byte i = 0; i < 4; i++) { - binkey[i] = encoded[i]; - decoded[i] = encoded[i]; - } - for(Int32 i = 0; i < this.key.Length; i++) { - binkey[i + 4] = this.key[i]; + for (Int32 i = 0; i < this.key.Length; i++) { + binkey[i] = this.key[i]; } + binkey[this.key.Length + 0] = encoded[2]; + binkey[this.key.Length + 1] = encoded[3]; + binkey[this.key.Length + 2] = encoded[0]; + binkey[this.key.Length + 3] = encoded[1]; + + Console.WriteLine("key: " + BitConverter.ToString(binkey).Replace("-", " ")); + SHA256 sha256Hash = SHA256.Create(); Byte[] crypto = sha256Hash.ComputeHash(binkey); - for(Int32 i = 0; i < encoded.Length-4; i++) { - decoded[i + 4] = (Byte)(encoded[i + 4] ^ crypto[crypto.Length - 1 - encoded.Length - 5 + i]); + sha256Hash.Dispose(); + + Console.WriteLine("sha: " + BitConverter.ToString(crypto).Replace("-", " ")); + + for (Int32 i = 0; i < encoded.Length; i++) { + decoded[i] = i < 4 ? encoded[i] : (Byte)(encoded[i] ^ crypto[crypto.Length - 1 - encoded.Length - 1 + i]); } + Console.WriteLine("Ee: " + BitConverter.ToString(decoded).Replace("-", " ")); return decoded; } } From f780c56e7cd49403d692dfa0b1f88c132f174c7d Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Wed, 15 Jan 2020 20:55:00 +0100 Subject: [PATCH 19/29] Parse the Crypto --- Lora-Bot/Parser/LoraParser.cs | 41 +++++++++++++++++++---------------- doc/Binaryformat.md | 36 +++++++++++++++--------------- 2 files changed, 40 insertions(+), 37 deletions(-) diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 898a2c3..5c63368 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -46,9 +46,14 @@ public void ReceivedPacket(Object sender, RecievedData data) { try { if (data.Data.Length == 18) { Byte[] decoded = this.DecodeData(data.Data); - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + decoded.Length + "]|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - } - if (data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { + Byte crc = this.SHA256Calc(decoded[0..17])[0]; + if(crc == decoded[17]) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data-En [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data-De [" + decoded.Length + "]|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + } else { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "|" + BitConverter.ToString(decoded).Replace("-", " ") + "| CRC:" + data.Crc); + } + } else if (data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### BinaryPacket p = this.ParseBinaryPacket(data.Data, data); if(p.Type == BinaryPacket.Typ.Data) { @@ -157,34 +162,32 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { Byte[] key = new Byte[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF }; private Byte[] DecodeData(Byte[] encoded) { - Console.WriteLine("En: " + BitConverter.ToString(encoded).Replace("-", " ")); Byte[] decoded = new Byte[encoded.Length]; if (encoded.Length != 18) { return encoded; } - Byte[] binkey = new Byte[this.key.Length + 4]; + Byte[] shakey = new Byte[this.key.Length + 4]; for (Int32 i = 0; i < this.key.Length; i++) { - binkey[i] = this.key[i]; + shakey[i] = this.key[i]; + } + for(Int32 i = 0; i < 4; i++) { + shakey[this.key.Length + i] = encoded[i]; } - binkey[this.key.Length + 0] = encoded[2]; - binkey[this.key.Length + 1] = encoded[3]; - binkey[this.key.Length + 2] = encoded[0]; - binkey[this.key.Length + 3] = encoded[1]; - - Console.WriteLine("key: " + BitConverter.ToString(binkey).Replace("-", " ")); - - SHA256 sha256Hash = SHA256.Create(); - Byte[] crypto = sha256Hash.ComputeHash(binkey); - sha256Hash.Dispose(); - Console.WriteLine("sha: " + BitConverter.ToString(crypto).Replace("-", " ")); + Byte[] crypto = this.SHA256Calc(shakey); for (Int32 i = 0; i < encoded.Length; i++) { - decoded[i] = i < 4 ? encoded[i] : (Byte)(encoded[i] ^ crypto[crypto.Length - 1 - encoded.Length - 1 + i]); + decoded[i] = i < 4 ? encoded[i] : (Byte)(encoded[i] ^ crypto[crypto.Length - encoded.Length + i]); } - Console.WriteLine("Ee: " + BitConverter.ToString(decoded).Replace("-", " ")); return decoded; } + + private Byte[] SHA256Calc(Byte[] data) { + SHA256 hashfunct = SHA256.Create(); + Byte[] sha = hashfunct.ComputeHash(data); + hashfunct.Dispose(); + return sha; + } } } diff --git a/doc/Binaryformat.md b/doc/Binaryformat.md index 119b704..880d877 100644 --- a/doc/Binaryformat.md +++ b/doc/Binaryformat.md @@ -11,10 +11,10 @@ schema message { ``` You need a secret for encrypt the data part in the message. This secret acts like an PSK so it must be known to both sides of the communication. This both will be summated together and generate a -sha2 `crypto = sha2(key<<32 | name<<16 | counter);`. +sha2 `crypto = sha2(key << 32 | counter << 16 | name);`. Now we bitwise XOR our data block with the crypto sha2 value. `data = dataraw ^ crypto`. -We CUT crypto to the length of data. +We CUT crypto to the length of data and use the last bytes, in this case the last 14 bytes. ## Data Section ```elm @@ -31,7 +31,7 @@ schema data { has_fix : 1; // 0 = true, 1 = false satelites : 4; // uint5_t } - counter_name_crc: uint8_t; // [13] + sha: uint8_t; // [13] } ``` * lan: Latitude coded as 4 Byte value. @@ -44,39 +44,39 @@ schema data { * has_date: If the gps module provides a valid date. * has_fix: If the gps module say there is a gps fix. * satelites: How many satelites the gps module see (reach from 0 to 15). -* coounter_name_crc: calculate a CRC8 value above the first 4 Byte (counter, name) of the complete packet, so you can maybe see if it was manipulated. +* sha: calculate a SHA256 value above the first 17 Byte of the complete packet and use the first byte, so you can maybe see if it was manipulated. ## Examples -We calculate a crypto and recovery it. For this example we use `key = 0xDEADBEEF;`. +We calculate a crypto and recovery it. For this example we use `key = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF;`. So this is now a very bad key. ### Encryption #### Using counter and name ```elm -counter = 0x0001; +counter = 0x0000; name = 0x4141; ``` #### Calculate xorkey ```elm key = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF; -shakey = sha256(key << 32 | name << 16 | counter); +shakey = sha256(key << 32 | counter << 16 | name); crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0x43557371C5CB113D83B20E337301; +crypro = 0xA6480EEAE95F35B8EEF0F7156358; ``` #### Create Datablock ```elm -data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x48 } -data = 0x004352050012980604D2785AFC48; +data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x03 } +data = 0x004352050012980604D2785AFC03; ``` #### Calculate message ```elm datac = data ^ crypto; -datac = 0x43162174C5D9893B876076698F49; +datac = 0xA60B5CEFE94DADBEEA228F4F9FFE; message = counter << 128 | name<<112 | datac; -message = 0x0001414143162174C5D9893B876076698F49; +message = 0x00014141A60B5CEFE94DADBEEA228F4F9FF5B; ``` ### Decryption -We get `message = 0x0001414143162174C5D9893B876076698F49;` as message. +We get `message = 0x00014141A60B5CEFE94DADBEEA228F4F9F5B;` as message. #### Reading counter and name ```elm counter = message >> 128; @@ -88,18 +88,18 @@ name = 0x4141; #### Calculating xorkey ```elm key = 0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF; -shakey = sha256(key << 32 | name << 16 | counter); +shakey = sha256(key << 32 | counter << 16 | name); crypto = shakey & 0x000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -crypro = 0x43557371C5CB113D83B20E337301; +crypro = 0xA6480EEAE95F35B8EEF0F7156358; ``` ### Decrypting Message ```elm datac = message & 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFF; -datac = 0x43162174C5D9893B876076698F49; +datac = 0xA60B5CEFE94DADBEEA228F4F9F5B; data = datac ^ crypto; -data = 0x004352050012980604D2785AFC48; +data = 0x004352050012980604D2785AFC03; ``` #### Decode Datablock ```elm -data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x48 } +data { 55.234,6.9812,123.4,3.5,0.9,0b11111100,0x03 } ``` \ No newline at end of file From 6c38cc17e3a2197254689a58f17df3ae2f5e0f68 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Wed, 15 Jan 2020 23:37:54 +0100 Subject: [PATCH 20/29] Parser now understand new Binary format, key will be read out of config --- Lora-Bot/Parser/LoraParser.cs | 97 ++++++++++++------- Lora-Bot/Program.cs | 4 +- Lora-Bot/config-example/settings.conf.example | 4 + doc/Binaryformat.md | 6 +- 4 files changed, 73 insertions(+), 38 deletions(-) diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 5c63368..630e08c 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; @@ -13,6 +14,19 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Parser { public class LoraParser { + private Byte[] CryptoKey; + + public LoraParser(String key) { + if(key == null || key.Length != 64) { + throw new ArgumentException("key is not a 64 Char String"); + } + Byte[] k = Enumerable.Range(0, key.Length).Where(x => x % 2 == 0).Select(x => Convert.ToByte(key.Substring(x, 2), 16)).ToArray(); + if(k.Length != 32) { + throw new Exception("key cant be converted to a 32 byte array"); + } + this.CryptoKey = k; + } + private readonly SortedDictionary> oldmarkerpos = new SortedDictionary>(); private readonly Object oldmarkerposlock = new Object(); @@ -48,8 +62,8 @@ public void ReceivedPacket(Object sender, RecievedData data) { Byte[] decoded = this.DecodeData(data.Data); Byte crc = this.SHA256Calc(decoded[0..17])[0]; if(crc == decoded[17]) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data-En [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data-De [" + decoded.Length + "]|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|"+ BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + BinaryPacket p = this.ParseBinaryPacket(decoded, data); } else { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "|" + BitConverter.ToString(decoded).Replace("-", " ") + "| CRC:" + data.Crc); } @@ -128,51 +142,68 @@ private DebugPacket ParseDebugPacket(Byte[] data, RecievedData recieveddata) { } private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { - Typ typ = Typ.Unknown; - if(data[0] == 'b') { - typ = Typ.Data; - } else if(data[0] == 'p') { - typ = Typ.Panic; - } - String name = data[2] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[1] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[2] }).Trim(); - Single lat = BitConverter.ToSingle(data, 3); - Single lon = BitConverter.ToSingle(data, 7); - Single hdop = (Single)data[11] / 10; - Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; - DateTime date = DateTime.TryParse(data[17].ToString().PadLeft(2, '0') + "." + data[18].ToString().PadLeft(2, '0') + "." + ((UInt16)(data[19] + 2000)).ToString().PadLeft(4, '0') + " " + data[14].ToString().PadLeft(2, '0') + ":" + data[15].ToString().PadLeft(2, '0') + ":" + data[16].ToString().PadLeft(2, '0'), out DateTime dv) ? dv : DateTime.MinValue; - Single battery = ((Single)data[20] + 230) / 100; - Tuple old = new Tuple(0, 0, DateTime.MinValue); - if(lat != 0 || lon != 0) { - lock(this.oldmarkerposlock) { - if(this.oldmarkerpos.ContainsKey(name)) { - this.oldmarkerpos[name] = new Tuple(lat, lon, DateTime.Now); - } else { - this.oldmarkerpos.Add(name, new Tuple(lat, lon, DateTime.Now)); + if(data.Length == 21) { + Typ typ = Typ.Unknown; + if(data[0] == 'b') { + typ = Typ.Data; + } else if(data[0] == 'p') { + typ = Typ.Panic; + } + String name = data[2] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[1] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[1], data[2] }).Trim(); + Single lat = BitConverter.ToSingle(data, 3); + Single lon = BitConverter.ToSingle(data, 7); + Single hdop = (Single)data[11] / 10; + Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; + DateTime date = DateTime.TryParse(data[17].ToString().PadLeft(2, '0') + "." + data[18].ToString().PadLeft(2, '0') + "." + ((UInt16)(data[19] + 2000)).ToString().PadLeft(4, '0') + " " + data[14].ToString().PadLeft(2, '0') + ":" + data[15].ToString().PadLeft(2, '0') + ":" + data[16].ToString().PadLeft(2, '0'), out DateTime dv) ? dv : DateTime.MinValue; + Single battery = ((Single)data[20] + 230) / 100; + Tuple old = new Tuple(0, 0, DateTime.MinValue); + if(lat != 0 || lon != 0) { + lock(this.oldmarkerposlock) { + if(this.oldmarkerpos.ContainsKey(name)) { + this.oldmarkerpos[name] = new Tuple(lat, lon, DateTime.Now); + } else { + this.oldmarkerpos.Add(name, new Tuple(lat, lon, DateTime.Now)); + } } } - } - lock(this.oldmarkerpos) { - if(this.oldmarkerpos.ContainsKey(name)) { - old = this.oldmarkerpos[name]; + lock(this.oldmarkerpos) { + if(this.oldmarkerpos.ContainsKey(name)) { + old = this.oldmarkerpos[name]; + } } + return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); + } else { + UInt16 counter = BitConverter.ToUInt16(data, 0); + String name = data[3] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[2] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[3] }).Trim(); + Single lat = BitConverter.ToSingle(data, 4); + Single lon = BitConverter.ToSingle(data, 8); + Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; + Single battery = ((Single)data[14] + 230) / 100; + Single hdop = (Single)data[15] / 10; + Typ typ = (data[16] & 0x80) != 0 ? Typ.Panic : Typ.Data; + Boolean has_time = (data[16] & 0x40) != 0 ? true : false; + Boolean has_date = (data[16] & 0x20) != 0 ? true : false; + Boolean has_fix = (data[16] & 0x10) != 0 ? true : false; + Byte sat = (Byte)(data[16] & 0x0F); + Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[3] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; + String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); + Console.WriteLine("counter: " + counter + " name: " + name + " lat: " + lat + " lon: " + lon + " height: " + height + " battery: " + battery + " hdop: " + hdop + " typ: " + typ + " has_time: " + has_time + " has_date: " + has_date + " has_fix: " + has_fix + " sat: " + sat + " cif: " + correct_if + " sha: " + hash); + return new BinaryPacket(name, typ, lat, lon, hdop, height, DateTime.Now, battery, recieveddata, new Tuple(0, 0, DateTime.MinValue)); } - return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); } - Byte[] key = new Byte[] { 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF, 0xDE, 0xAD, 0xBE, 0xEF }; - private Byte[] DecodeData(Byte[] encoded) { Byte[] decoded = new Byte[encoded.Length]; if (encoded.Length != 18) { return encoded; } - Byte[] shakey = new Byte[this.key.Length + 4]; - for (Int32 i = 0; i < this.key.Length; i++) { - shakey[i] = this.key[i]; + Byte[] shakey = new Byte[this.CryptoKey.Length + 4]; + for (Int32 i = 0; i < this.CryptoKey.Length; i++) { + shakey[i] = this.CryptoKey[i]; } for(Int32 i = 0; i < 4; i++) { - shakey[this.key.Length + i] = encoded[i]; + shakey[this.CryptoKey.Length + i] = encoded[i]; } Byte[] crypto = this.SHA256Calc(shakey); diff --git a/Lora-Bot/Program.cs b/Lora-Bot/Program.cs index ce4e889..70c21f8 100644 --- a/Lora-Bot/Program.cs +++ b/Lora-Bot/Program.cs @@ -21,9 +21,9 @@ public Program(String[] _) { InIReader settings = InIReader.GetInstance("settings"); this.logger.SetPath(settings.GetValue("logging", "path")); - LoraController lora = new LoraController(settings.GetSection("lora")); - LoraParser parser = new LoraParser(); + LoraParser parser = new LoraParser(settings.GetValue("general", "key")); + LoraController lora = new LoraController(settings.GetSection("lora")); lora.Received += parser.ReceivedPacket; this.ModulLoader("Fraunhofer.Fit.IoT.Bots.LoraBot.Moduls", parser); diff --git a/Lora-Bot/config-example/settings.conf.example b/Lora-Bot/config-example/settings.conf.example index 3e09569..b142b5a 100644 --- a/Lora-Bot/config-example/settings.conf.example +++ b/Lora-Bot/config-example/settings.conf.example @@ -1,6 +1,10 @@ [logging] path=/var/log/lorabot.log +[general] +key=DEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF +; MUST BE 32 BYTES in Hex! + ;[lora] ;debug=true ;type=Dragino diff --git a/doc/Binaryformat.md b/doc/Binaryformat.md index 880d877..8ed518d 100644 --- a/doc/Binaryformat.md +++ b/doc/Binaryformat.md @@ -26,9 +26,9 @@ schema data { hdop : uint8_t; // [11] status : bitfield : uint8_t { // [12] message_type : 1 // 0 = regular, 1 = eventbased - has_time : 1; // 0 = true, 1 = false - has_date : 1; // 0 = true, 1 = false - has_fix : 1; // 0 = true, 1 = false + has_time : 1; // 1 = true, 0 = false + has_date : 1; // 1 = true, 0 = false + has_fix : 1; // 1 = true, 0 = false satelites : 4; // uint5_t } sha: uint8_t; // [13] From 885bbfdc2e14e78f9815729d7820844c4eac7998 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Thu, 16 Jan 2020 13:32:35 +0100 Subject: [PATCH 21/29] Parsing new Binary Format --- Lora-Bot/Events/GpsUpdateEvent.cs | 4 +++ Lora-Bot/Events/TrackerUpdateEvent.cs | 10 ++++++ Lora-Bot/Models/BinaryPacket.cs | 46 +++++++++++++++++++++++++++ Lora-Bot/Parser/LoraParser.cs | 11 +++++-- 4 files changed, 68 insertions(+), 3 deletions(-) diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs index 65fe065..f3f9ab7 100644 --- a/Lora-Bot/Events/GpsUpdateEvent.cs +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -26,6 +26,10 @@ public Double Longitude { public DateTime Time { get; set; } + + public Byte Satelites { + get; set; + } #endregion [Obsolete("Should do by client")] diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs index 56e470c..3e51c50 100644 --- a/Lora-Bot/Events/TrackerUpdateEvent.cs +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -12,6 +12,16 @@ public Double BatteryLevel { } public String Host => Environment.MachineName; + + public UInt16 Counter { get; set; } + + public Boolean HasTime { get; set; } + + public Boolean HasDate { get; set; } + + public Boolean CorrectInterface { get; set; } + + public String Hash { get; set; } #endregion #region Global Lora Data diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs index 37e0f25..64fa452 100644 --- a/Lora-Bot/Models/BinaryPacket.cs +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -45,6 +45,52 @@ public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Sin } } + public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, UInt16 counter, Boolean has_time, Boolean has_date, Boolean has_fix, Byte sat, Boolean correct_if, String hash, RecievedData recieveddata) { + if (typ == LoraParser.Typ.Data) { + this.Data = new DataUpdateEvent() { + Name = name, + BatteryLevel = battery, + Counter = counter, + HasTime = has_time, + HasDate = has_date, + CorrectInterface = correct_if, + Hash = hash, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Fix = has_fix, + Satelites = sat + } + }; + this.Type = Typ.Data; + this.SetLoraData(recieveddata, this.Data); + } else if (typ == LoraParser.Typ.Panic) { + this.Panic = new PanicUpdateEvent() { + Name = name, + BatteryLevel = battery, + Counter = counter, + HasTime = has_time, + HasDate = has_date, + CorrectInterface = correct_if, + Hash = hash, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Fix = has_fix, + Satelites = sat + } + }; + this.Type = Typ.Panic; + this.SetLoraData(recieveddata, this.Panic); + } else { + this.Type = Typ.Error; + } + } + public enum Typ { Data, Panic, diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 630e08c..853b3af 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -62,8 +62,14 @@ public void ReceivedPacket(Object sender, RecievedData data) { Byte[] decoded = this.DecodeData(data.Data); Byte crc = this.SHA256Calc(decoded[0..17])[0]; if(crc == decoded[17]) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|"+ BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); BinaryPacket p = this.ParseBinaryPacket(decoded, data); + if (p.Type == BinaryPacket.Typ.Data) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + this.DataUpdates(sender, p.Data); + } else if (p.Type == BinaryPacket.Typ.Panic) { + Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); + this.PanicUpdates(sender, p.Panic); + } } else { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "|" + BitConverter.ToString(decoded).Replace("-", " ") + "| CRC:" + data.Crc); } @@ -187,8 +193,7 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { Byte sat = (Byte)(data[16] & 0x0F); Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[3] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); - Console.WriteLine("counter: " + counter + " name: " + name + " lat: " + lat + " lon: " + lon + " height: " + height + " battery: " + battery + " hdop: " + hdop + " typ: " + typ + " has_time: " + has_time + " has_date: " + has_date + " has_fix: " + has_fix + " sat: " + sat + " cif: " + correct_if + " sha: " + hash); - return new BinaryPacket(name, typ, lat, lon, hdop, height, DateTime.Now, battery, recieveddata, new Tuple(0, 0, DateTime.MinValue)); + return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, counter, has_time, has_date, has_fix, sat, correct_if, hash, recieveddata); } } From e527d80342dc6da4bd94863502afa4be7008c773 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Fri, 17 Jan 2020 14:59:25 +0100 Subject: [PATCH 22/29] BF dedect correct interface --- Lora-Bot/Parser/LoraParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index 853b3af..bcb3849 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -191,7 +191,7 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { Boolean has_date = (data[16] & 0x20) != 0 ? true : false; Boolean has_fix = (data[16] & 0x10) != 0 ? true : false; Byte sat = (Byte)(data[16] & 0x0F); - Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[3] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; + Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[2] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, counter, has_time, has_date, has_fix, sat, correct_if, hash, recieveddata); } From 562f1550e49af5253595a476426f3a4e21ee5009 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Fri, 17 Jan 2020 23:37:57 +0100 Subject: [PATCH 23/29] Preparing release --- .github/workflows/dotnetcore.yml | 65 +- CHANGELOG.md | 84 +- Lora-Bot/Events/DataUpdateEvent.cs | 13 - Lora-Bot/Events/GpsUpdateEvent.cs | 18 +- Lora-Bot/Events/LocationUpdateEvent.cs | 23 + Lora-Bot/Events/PanicUpdateEvent.cs | 13 - Lora-Bot/Events/TrackerUpdateEvent.cs | 14 +- Lora-Bot/Lora-Bot.csproj | 17 +- Lora-Bot/Models/BinaryPacket.cs | 130 +-- Lora-Bot/Models/DebugPacket.cs | 6 +- Lora-Bot/Moduls/Txtout.cs | 2 +- Lora-Bot/Parser/LoraParser.cs | 33 +- Lora-Bot/dpkg/control | 2 +- Lora-Bot/dpkg/create-Builds.bat | 1 + .../{lorabot-logrotate => logrotate-lorabot} | 0 Lora-Bot/dpkg/make-deb.sh | 60 +- Lora-Bot/dpkg/postinst | 14 +- Lora-Bot/dpkg/preinst | 4 + Lora-Bot/dpkg/prerm | 8 +- .../dpkg/{lorabot.service => service-lorabot} | 8 +- doc/Mqttformat.md | 794 +++++++++++------- doc/Mqttformat.yml | 349 ++++++++ 22 files changed, 1070 insertions(+), 588 deletions(-) delete mode 100644 Lora-Bot/Events/DataUpdateEvent.cs create mode 100644 Lora-Bot/Events/LocationUpdateEvent.cs delete mode 100644 Lora-Bot/Events/PanicUpdateEvent.cs rename Lora-Bot/dpkg/{lorabot-logrotate => logrotate-lorabot} (100%) rename Lora-Bot/dpkg/{lorabot.service => service-lorabot} (72%) create mode 100644 doc/Mqttformat.yml diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 88c9d7c..646e1a1 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -1,5 +1,4 @@ -name: Build, Test, Publish and Dockerise TTN-Bridge -FAIL! +name: Build, Test, Publish Lora-Bot on: [push] jobs: @@ -10,13 +9,17 @@ jobs: - name: Checkout parent project with dependencys uses: actions/checkout@v1 with: - repository: MONICA-Project/ttn-bridge-project + repository: MONICA-Project/lora-project ref: refs/heads/master submodules: true - name: Checkout last versions - run: git -C TTN-Bridge checkout --progress --force ${{ github.sha }} - working-directory: ../ttn-bridge-project + run: git -C Lora checkout --progress --force dotnetcore + working-directory: ../lora-project + + - name: Checkout last versions + run: git -C Lora-Bot checkout --progress --force ${{ github.sha }} + working-directory: ../lora-project - name: Install dotnet uses: actions/setup-dotnet@v1 @@ -24,18 +27,17 @@ jobs: dotnet-version: 3.0.100 - name: Build with dotnet - run: dotnet build TTN-Bridge.sln --configuration Release - working-directory: ../ttn-bridge-project/TTN-Bridge + run: dotnet build Lora-Bot.sln --configuration Release + working-directory: ../lora-project/Lora-Bot - name: Create deb files if: success() run: | mkdir ../../../Builds chmod oug+x make-deb.sh - ./make-deb.sh amd64 ./make-deb.sh armhf id: create_deb - working-directory: ../ttn-bridge-project/TTN-Bridge/TTN-Bridge/dpkg + working-directory: ../lora-project/Lora-Bot/Lora-Bot/dpkg - name: Create release if: success() @@ -50,18 +52,6 @@ jobs: draft: false prerelease: true - - name: Upload release asset amd64 - if: success() - id: upload-release-asset-amd64 - uses: actions/upload-release-asset@v1.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ steps.nightly_release.outputs.upload_url }} - asset_path: ../ttn-bridge-project/Builds/amd64-${{ steps.create_deb.outputs.debuilderfile }} - asset_name: amd64-${{ steps.create_deb.outputs.debuilderfile }} - asset_content_type: application/x-deb - - name: Upload release asset armhf if: success() id: upload-release-asset-armhf @@ -70,41 +60,10 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.nightly_release.outputs.upload_url }} - asset_path: ../ttn-bridge-project/Builds/armhf-${{ steps.create_deb.outputs.debuilderfile }} + asset_path: ../lora-project/Builds/armhf-${{ steps.create_deb.outputs.debuilderfile }} asset_name: armhf-${{ steps.create_deb.outputs.debuilderfile }} asset_content_type: application/x-deb - docker: - name: Build and push dockerfile - runs-on: ubuntu-latest - steps: - - name: Checkout parent project with dependencys - uses: actions/checkout@v1 - with: - repository: MONICA-Project/ttn-bridge-project - ref: refs/heads/master - submodules: true - - - name: Checkout last versions - run: git -C TTN-Bridge checkout --progress --force ${{ github.sha }} - working-directory: ../ttn-bridge-project - - - name: Docker build - id: docker_build - run: | - DOCKERTAG=$(date +%Y%m%d%H%M%S) - echo "##[set-output name=dockertag;]$DOCKERTAG" - docker build . -t monicaproject/ttn-bridge:latest -t monicaproject/ttn-bridge:$DOCKERTAG - working-directory: ../ttn-bridge-project - - - name: Docker-compose publish - if: success() - run: | - echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin ${INPUT_REGISTRY} - docker push monicaproject/ttn-bridge:latest - docker push monicaproject/ttn-bridge:${{ steps.docker_build.outputs.dockertag }} - working-directory: ../ttn-bridge-project - # VMAJOR=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 1) # VMINOR=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 2) # VBUILD=$(grep -e "" ../TTN-Bridge_Core.csproj | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 3) diff --git a/CHANGELOG.md b/CHANGELOG.md index e21beb4..8763195 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,196 +1,152 @@ # Changelog -## 1.8.3 +## 2.0.0 - The total rewrite +### New Features + +* Add Github Actions +* Parsing data is now in this software part +* Add new fileds in json +* Documenting the Binary transmission +### Bugfixes +### Changes +* Debugging will be done over configure file +* Refactoring +* Porting to .NET Core + +## 1.8.4 ### New Features +### Bugfixes +* Fixing a bug related to threaded working with data + +### Changes +## 1.8.3 +### New Features * Add an Output for Panic Events ### Bugfixes - * Implement the new ConnectorDataMqtt ### Changes - * Remove Scral and the Configfile, because its an own Project ## 1.8.2 - ### New Features - ### Bugfixes - * Bugfix, create also an event for sending normal loradata when update panic ### Changes ## 1.8.1 - ### New Features - * Add Hostname to MQTT, so you can see from witch device the data is recieved ### Bugfixes - ### Changes ## 1.8.0 - ### New Features - * Add field that indicates when the last gps position was recieved, change all times to UTC ### Bugfixes - ### Changes ## 1.7.3 - ### New Features - * Parsing new Status format and Panic Package ### Bugfixes - ### Changes ## 1.7.2 - ### New Features - ### Bugfixes - ### Changes - * Update to local librarys ## 1.7.1 - ### New Features - * Fixing binary data transmission & fixing Scral Plugin ### Bugfixes - ### Changes ## 1.7.0 - ### New Features - * Adding IC800A Lora-Reciever ### Bugfixes - ### Changes ## 1.6.2 - ### New Features - ### Bugfixes - ### Changes - * Adding a test for LoraBinary ## 1.6.1 - ### New Features - ### Bugfixes - * Fixing parsing bug with linebreaks in Lora ### Changes ## 1.6.0 - ### New Features - * Implement Height in LoraBot ### Bugfixes - ### Changes ## 1.5.1 - ### New Features - ### Bugfixes - ### Changes - * Dependencies in debian Packet cleaned ## 1.5.0 - ### New Features - * Send over Mqtt the new status items and refactoring ### Bugfixes - ### Changes ## 1.4.1 - ### New Features - ### Bugfixes - ### Changes - * Remove old Wirelesscode and Rename some Classes ## 1.4.0 - ### New Features - * Adding Debugmode for finetuning Lora-Trackers ### Bugfixes - ### Changes ## 1.3.0 - ### New Features - ### Bugfixes - ### Changes - * Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value ## 1.2.0 - ### New Features - ### Bugfixes - ### Changes - * Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile ## 1.1.0.0 - ### New Features - ### Bugfixes - ### Changes - * Update Scral addresses ## 1.0.0.0 - ### New Features - * First working Version ### Bugfixes - ### Changes diff --git a/Lora-Bot/Events/DataUpdateEvent.cs b/Lora-Bot/Events/DataUpdateEvent.cs deleted file mode 100644 index d7bd7a9..0000000 --- a/Lora-Bot/Events/DataUpdateEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { - public class DataUpdateEvent : TrackerUpdateEvent { - public GpsUpdateEvent Gps { - get; set; - } - - public override String MqttTopic() => "data/" + base.MqttTopic(); - - public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); - } -} diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs index f3f9ab7..8317875 100644 --- a/Lora-Bot/Events/GpsUpdateEvent.cs +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -7,6 +7,15 @@ public Boolean Fix { get; set; } + public Boolean HasDate { + get; set; + } + + public Boolean HasTime { + get; set; + } + + public Double Hdop { get; set; } @@ -22,10 +31,6 @@ public Double Latitude { public Double Longitude { get; set; } - - public DateTime Time { - get; set; - } public Byte Satelites { get; set; @@ -45,6 +50,11 @@ public DateTime LastGPSPos { get; set; } + [Obsolete("Will be not Transmitted anymore")] + public DateTime Time { + get; set; + } + public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; //public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; diff --git a/Lora-Bot/Events/LocationUpdateEvent.cs b/Lora-Bot/Events/LocationUpdateEvent.cs new file mode 100644 index 0000000..05ca076 --- /dev/null +++ b/Lora-Bot/Events/LocationUpdateEvent.cs @@ -0,0 +1,23 @@ +using System; + +using Fraunhofer.Fit.IoT.Bots.LoraBot.Parser; + +namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { + public class LocationUpdateEvent : TrackerUpdateEvent { + private readonly LoraParser.Typ ptype; + + public LocationUpdateEvent(LoraParser.Typ typ) => this.ptype = typ; + + public UInt16 Counter { + get; set; + } + + public GpsUpdateEvent Gps { + get; set; + } + + public override String MqttTopic() => (this.ptype == LoraParser.Typ.Panic ? "panic/" : "data/") + base.MqttTopic(); + + public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); + } +} diff --git a/Lora-Bot/Events/PanicUpdateEvent.cs b/Lora-Bot/Events/PanicUpdateEvent.cs deleted file mode 100644 index ebdbe91..0000000 --- a/Lora-Bot/Events/PanicUpdateEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; - -namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Events { - public class PanicUpdateEvent : TrackerUpdateEvent { - public GpsUpdateEvent Gps { - get; set; - } - - public override String MqttTopic() => "panic/" + base.MqttTopic(); - - public override String ToString() => base.ToString() + " -- " + "GPS: " + this.Gps.ToString(); - } -} diff --git a/Lora-Bot/Events/TrackerUpdateEvent.cs b/Lora-Bot/Events/TrackerUpdateEvent.cs index 3e51c50..2da8ffe 100644 --- a/Lora-Bot/Events/TrackerUpdateEvent.cs +++ b/Lora-Bot/Events/TrackerUpdateEvent.cs @@ -13,15 +13,13 @@ public Double BatteryLevel { public String Host => Environment.MachineName; - public UInt16 Counter { get; set; } - - public Boolean HasTime { get; set; } - - public Boolean HasDate { get; set; } - - public Boolean CorrectInterface { get; set; } + public Boolean CorrectInterface { + get; set; + } - public String Hash { get; set; } + public String Hash { + get; set; + } #endregion #region Global Lora Data diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index 6f0cb4d..691cee9 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -8,14 +8,15 @@ Program that runs on a device and process the Lora traffic from the Lora library Fraunhofer FIT BlubbFish - 1.8.4 + 2.0.0 Copyright © Fraunhofer FIT, BlubbFish 2018 - 08.07.2019 LICENSE de-DE https://github.com/MONICA-Project/lora-bot https://github.com/MONICA-Project/lora-bot.git git - 1.8.4 Fixing a bug related to threaded working with data + 2.0.0 The total rewrite +1.8.4 Fixing a bug related to threaded working with data 1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend 1.8.2 Bugfix, create also an event for sending normal loradata when update panic 1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved @@ -48,6 +49,7 @@ + @@ -63,5 +65,16 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs index 64fa452..9587751 100644 --- a/Lora-Bot/Models/BinaryPacket.cs +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -7,106 +7,54 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class BinaryPacket : Packet { public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, DateTime date, Single battery, RecievedData recieveddata, Tuple old) { + this.TransferData = new LocationUpdateEvent(typ) { + Name = name, + BatteryLevel = battery, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Time = date, + Fix = lat != 0 || lon != 0 + } + }; + this.Type = typ; + this.SetLoraData(recieveddata, this.TransferData); if(typ == LoraParser.Typ.Data) { - this.Data = new DataUpdateEvent() { - Name = name, - BatteryLevel = battery, - Gps = new GpsUpdateEvent() { - Latitude = lat, - Longitude = lon, - Hdop = hdop, - Height = height, - Time = date, - Fix = lat != 0 || lon != 0, - LastLatitude = old.Item1, - LastLongitude = old.Item2, - LastGPSPos = old.Item3 - } - }; - this.Type = Typ.Data; - this.SetLoraData(recieveddata, this.Data); - } else if(typ == LoraParser.Typ.Panic) { - this.Panic = new PanicUpdateEvent() { - Name = name, - BatteryLevel = battery, - Gps = new GpsUpdateEvent() { - Latitude = lat, - Longitude = lon, - Hdop = hdop, - Height = height, - Time = date, - Fix = lat != 0 || lon != 0 - } - }; - this.Type = Typ.Panic; - this.SetLoraData(recieveddata, this.Panic); - } else { - this.Type = Typ.Error; - } + this.TransferData.Gps.LastLatitude = old.Item1; + this.TransferData.Gps.LastLongitude = old.Item2; + this.TransferData.Gps.LastGPSPos = old.Item3; + } } public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, UInt16 counter, Boolean has_time, Boolean has_date, Boolean has_fix, Byte sat, Boolean correct_if, String hash, RecievedData recieveddata) { - if (typ == LoraParser.Typ.Data) { - this.Data = new DataUpdateEvent() { - Name = name, - BatteryLevel = battery, - Counter = counter, + this.TransferData = new LocationUpdateEvent(typ) { + Name = name, + BatteryLevel = battery, + Counter = counter, + CorrectInterface = correct_if, + Hash = hash, + Gps = new GpsUpdateEvent() { + Latitude = lat, + Longitude = lon, + Hdop = hdop, + Height = height, + Fix = has_fix, + Satelites = sat, HasTime = has_time, - HasDate = has_date, - CorrectInterface = correct_if, - Hash = hash, - Gps = new GpsUpdateEvent() { - Latitude = lat, - Longitude = lon, - Hdop = hdop, - Height = height, - Fix = has_fix, - Satelites = sat - } - }; - this.Type = Typ.Data; - this.SetLoraData(recieveddata, this.Data); - } else if (typ == LoraParser.Typ.Panic) { - this.Panic = new PanicUpdateEvent() { - Name = name, - BatteryLevel = battery, - Counter = counter, - HasTime = has_time, - HasDate = has_date, - CorrectInterface = correct_if, - Hash = hash, - Gps = new GpsUpdateEvent() { - Latitude = lat, - Longitude = lon, - Hdop = hdop, - Height = height, - Fix = has_fix, - Satelites = sat - } - }; - this.Type = Typ.Panic; - this.SetLoraData(recieveddata, this.Panic); - } else { - this.Type = Typ.Error; - } - } - - public enum Typ { - Data, - Panic, - Error + HasDate = has_date + } + }; + this.Type = typ; + this.SetLoraData(recieveddata, this.TransferData); } - public Typ Type { + public LoraParser.Typ Type { get; set; - } - - public DataUpdateEvent Data { - get; - private set; - } + } = LoraParser.Typ.Unknown; - public PanicUpdateEvent Panic { + public LocationUpdateEvent TransferData { get; private set; } diff --git a/Lora-Bot/Models/DebugPacket.cs b/Lora-Bot/Models/DebugPacket.cs index d6c1f06..5409caa 100644 --- a/Lora-Bot/Models/DebugPacket.cs +++ b/Lora-Bot/Models/DebugPacket.cs @@ -6,7 +6,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { class DebugPacket : Packet { - public DebugPacket(String text, String name, Int32 version, String ipaddress, String wifissid, Boolean wifiactive, Double batteryLevel, Int32 freqOffset, LoraParser.Status devicestatus, RecievedData recieveddata) { + public DebugPacket(String text, String name, Int32 version, String ipaddress, String wifissid, Boolean wifiactive, Double batteryLevel, Int32 freqOffset, LoraParser.Status devicestatus, Boolean correct_if, String hash, RecievedData recieveddata) { this.Text = text; if(devicestatus == LoraParser.Status.Unknown) { this.Type = Typ.Error; @@ -19,7 +19,9 @@ public DebugPacket(String text, String name, Int32 version, String ipaddress, St WifiSsid = wifissid, WifiActive = wifiactive, FrequencyOffset = freqOffset, - DeviceStatus = devicestatus.ToString() + DeviceStatus = devicestatus.ToString(), + Hash = hash, + CorrectInterface = correct_if }; this.SetLoraData(recieveddata, this.Status); } diff --git a/Lora-Bot/Moduls/Txtout.cs b/Lora-Bot/Moduls/Txtout.cs index a2166db..e90c666 100644 --- a/Lora-Bot/Moduls/Txtout.cs +++ b/Lora-Bot/Moduls/Txtout.cs @@ -29,7 +29,7 @@ public Txtout(LoraParser lib, InIReader settings) : base(lib, settings) { protected override void LibUpadteThread(Object state) { try { - if(state is DataUpdateEvent data) { + if(state is LocationUpdateEvent data) { String s = data.Name + "," + data.Receivedtime.ToString("o") + "," + data.Gps.Latitude + "," + data.Gps.Longitude + "," + data.Rssi + "," + data.PacketRssi + "," + data.Snr + ",https://www.google.de/maps?q=" + data.Gps.Latitude + "%2C" + data.Gps.Longitude; this.file.WriteLine(s); this.file.Flush(); diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index bcb3849..ab94b7a 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -14,7 +14,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Parser { public class LoraParser { - private Byte[] CryptoKey; + private readonly Byte[] CryptoKey; public LoraParser(String key) { if(key == null || key.Length != 64) { @@ -30,8 +30,8 @@ public LoraParser(String key) { private readonly SortedDictionary> oldmarkerpos = new SortedDictionary>(); private readonly Object oldmarkerposlock = new Object(); - public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); - public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); + public delegate void UpdateDataEvent(Object sender, LocationUpdateEvent e); + public delegate void UpdatePanicEvent(Object sender, LocationUpdateEvent e); public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); public event UpdateDataEvent DataUpdate; public event UpdatePanicEvent PanicUpdate; @@ -50,9 +50,9 @@ public enum Typ { Unknown } - private async void DataUpdates(Object sender, DataUpdateEvent e) => await Task.Run(() => this.DataUpdate?.Invoke(sender, e)); + private async void DataUpdates(Object sender, LocationUpdateEvent e) => await Task.Run(() => this.DataUpdate?.Invoke(sender, e)); - private async void PanicUpdates(Object sender, PanicUpdateEvent e) => await Task.Run(() => this.PanicUpdate?.Invoke(sender, e)); + private async void PanicUpdates(Object sender, LocationUpdateEvent e) => await Task.Run(() => this.PanicUpdate?.Invoke(sender, e)); private async void StatusUpdates(Object sender, StatusUpdateEvent e) => await Task.Run(() => this.StatusUpdate?.Invoke(sender, e)); @@ -63,12 +63,12 @@ public void ReceivedPacket(Object sender, RecievedData data) { Byte crc = this.SHA256Calc(decoded[0..17])[0]; if(crc == decoded[17]) { BinaryPacket p = this.ParseBinaryPacket(decoded, data); - if (p.Type == BinaryPacket.Typ.Data) { + if (p.Type == Typ.Data) { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.DataUpdates(sender, p.Data); - } else if (p.Type == BinaryPacket.Typ.Panic) { + this.DataUpdates(sender, p.TransferData); + } else if (p.Type == Typ.Panic) { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + data.Data.Length + "] E|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| D|" + BitConverter.ToString(decoded).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.PanicUpdates(sender, p.Panic); + this.PanicUpdates(sender, p.TransferData); } } else { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "|" + BitConverter.ToString(decoded).Replace("-", " ") + "| CRC:" + data.Crc); @@ -76,12 +76,12 @@ public void ReceivedPacket(Object sender, RecievedData data) { } else if (data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### BinaryPacket p = this.ParseBinaryPacket(data.Data, data); - if(p.Type == BinaryPacket.Typ.Data) { + if(p.Type == Typ.Data) { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.DataUpdates(sender, p.Data); - } else if(p.Type == BinaryPacket.Typ.Panic) { + this.DataUpdates(sender, p.TransferData); + } else if(p.Type == Typ.Panic) { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.PanicUpdates(sender, p.Panic); + this.PanicUpdates(sender, p.TransferData); } else { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| CRC:" + data.Crc); } @@ -141,7 +141,9 @@ private DebugPacket ParseDebugPacket(Byte[] data, RecievedData recieveddata) { status = Status.Powersave; } } - return new DebugPacket(text, name, version, ipaddress, wifissid, wifiactive, batteryLevel, freqOffset, status, recieveddata); + Boolean correct_if = recieveddata is Ic880aRecievedObj ? name.ToCharArray()[0] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; + String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); + return new DebugPacket(text, name, version, ipaddress, wifissid, wifiactive, batteryLevel, freqOffset, status, correct_if, hash, recieveddata); } else { return new DebugPacket() { Type = DebugPacket.Typ.Error }; } @@ -178,7 +180,7 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { } } return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); - } else { + } else if(data.Length == 18) { UInt16 counter = BitConverter.ToUInt16(data, 0); String name = data[3] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[2] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[3] }).Trim(); Single lat = BitConverter.ToSingle(data, 4); @@ -195,6 +197,7 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, counter, has_time, has_date, has_fix, sat, correct_if, hash, recieveddata); } + return null; } private Byte[] DecodeData(Byte[] encoded) { diff --git a/Lora-Bot/dpkg/control b/Lora-Bot/dpkg/control index 707a74a..bb17d45 100644 --- a/Lora-Bot/dpkg/control +++ b/Lora-Bot/dpkg/control @@ -3,7 +3,7 @@ Version: x.x-x Section: base Priority: optional Architecture: any -Depends: mono-runtime (>= 5.18), wiringpi (>= 2.46), libmono-posix4.0-cil (>= 5.18) +Depends: wiringpi (>= 2.50), dotnet-runtime-3.0 (>= 3.0.1) Maintainer: BlubbFish Description: Lora-Bot Lora-Bot is a Lora gateway diff --git a/Lora-Bot/dpkg/create-Builds.bat b/Lora-Bot/dpkg/create-Builds.bat index 9cc5846..28e447d 100644 --- a/Lora-Bot/dpkg/create-Builds.bat +++ b/Lora-Bot/dpkg/create-Builds.bat @@ -1,2 +1,3 @@ +mkdir ..\..\..\Builds bash.exe -c "./make-deb.sh armhf" pause \ No newline at end of file diff --git a/Lora-Bot/dpkg/lorabot-logrotate b/Lora-Bot/dpkg/logrotate-lorabot similarity index 100% rename from Lora-Bot/dpkg/lorabot-logrotate rename to Lora-Bot/dpkg/logrotate-lorabot diff --git a/Lora-Bot/dpkg/make-deb.sh b/Lora-Bot/dpkg/make-deb.sh index 518126c..439d02f 100644 --- a/Lora-Bot/dpkg/make-deb.sh +++ b/Lora-Bot/dpkg/make-deb.sh @@ -2,26 +2,35 @@ HOMEDIR=$HOME ROOT="$HOMEDIR/deb" -OUTPUT="../bin/Release" +OUTPUT="../bin/Release/netcoreapp3.0" -EXEC="$ROOT/usr/local/bin/lorabot" -CONFIG="$ROOT/etc/lorabot" +DEBNAME="lorabot" +CSPROJFILE="Lora-Bot.csproj" + +EXEC="$ROOT/usr/local/bin/$DEBNAME" +CONFIG="$ROOT/etc/$DEBNAME" SYSTEMD="$ROOT/lib/systemd/system" LOGROTATE="$ROOT/etc/logrotate.d" +echo "Catch all paths together for $DEBNAME." + DEBIAN="$ROOT/DEBIAN" -VMAJOR=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 1) -VMINOR=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 2) -VBUILD=$(grep -e "^\[assembly: AssemblyVersion(\"" ../Properties/AssemblyInfo.cs | cut -d'"' -f 2 | cut -d'.' -f 3) +VMAJOR=$(grep -e "" ../$CSPROJFILE | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 1) +VMINOR=$(grep -e "" ../$CSPROJFILE | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 2) +VBUILD=$(grep -e "" ../$CSPROJFILE | cut -d'>' -f 2 | cut -d'<' -f 1 | cut -d'.' -f 3) ARCHT=$1 +echo "Versionsumber parsed: $VMAJOR.$VMINOR-$VBUILD." + mkdir -p $EXEC mkdir -p $CONFIG mkdir -p $DEBIAN mkdir -p $SYSTEMD mkdir -p $LOGROTATE -cp control $DEBIAN +echo "Created directorys." + +cp control $DEBIAN/control cp preinst $DEBIAN cp postinst $DEBIAN cp prerm $DEBIAN @@ -29,23 +38,44 @@ sed -i s/Version:\ x\.x-x/"Version: $VMAJOR.$VMINOR-$VBUILD"/ $DEBIAN/control sed -i s/Architecture:\ any/"Architecture: $ARCHT"/ $DEBIAN/control chmod 755 $DEBIAN -R -cp lorabot.service $SYSTEMD -chmod 644 $SYSTEMD/lorabot.service +echo "Copy deb control files." -cp $OUTPUT/*.exe $EXEC/ -#cp $OUTPUT/gpio.2.44 $EXEC/ -#cp $OUTPUT/libwiringPi.so.2.44 $EXEC/ +cp "service-$DEBNAME" "$SYSTEMD/$DEBNAME.service" +chmod 644 $SYSTEMD/"$DEBNAME.service" + +echo "Copy $DEBNAME.service to $SYSTEMD." + +cp $OUTPUT/*.runtimeconfig.json $EXEC/ find $OUTPUT -name \*.dll -exec cp {} $EXEC/ \; chmod 644 $EXEC/* chmod 755 $EXEC +echo "Copy programm files to $EXEC." + cp $OUTPUT/config-example/* $CONFIG chmod 644 $CONFIG/* chmod 755 $CONFIG -cp lorabot-logrotate $LOGROTATE/lorabot +echo "Copy example-conf to $CONFIG." + +cp "logrotate-$DEBNAME" "$LOGROTATE/$DEBNAME.conf" chmod 644 $LOGROTATE/* +echo "Copy $DEBNAME.conf to $LOGROTATE." + dpkg-deb --build $ROOT -mv $HOMEDIR/deb.deb ../../../Builds/"$ARCHT-lorabot_$VMAJOR.$VMINOR-$VBUILD.deb" -rm $HOMEDIR/deb -r \ No newline at end of file + +echo "Build deb packet." + + +TARGETFILE="$DEBNAME""_$VMAJOR.$VMINOR-$VBUILD.deb" +mv $HOMEDIR/deb.deb "../../../Builds/$ARCHT-$TARGETFILE" + +echo "Move $ARCHT-$TARGETFILE to Builds." + +rm $HOMEDIR/deb -r + +echo "Remove $HOMEDIR/deb." + +echo "##[set-output name=debuilderfile;]$TARGETFILE" +echo "##[set-output name=builddaterelease;]$(date +"%F_%H%M%S")" \ No newline at end of file diff --git a/Lora-Bot/dpkg/postinst b/Lora-Bot/dpkg/postinst index c141c5f..bbbc6b4 100644 --- a/Lora-Bot/dpkg/postinst +++ b/Lora-Bot/dpkg/postinst @@ -1,9 +1,15 @@ #!/bin/bash -systemctl enable lorabot +DEBNAME="lorabot" + +systemctl enable $DEBNAME systemctl daemon-reload -if [ -f /tmp/lorabot_service_runner ]; then - service lorabot start - rm /tmp/lorabot_service_runner +touch /var/log/$DEBNAME.log +chown loragwbot:loragwbot /var/log/$DEBNAME.log +chmod 644 /var/log/$DEBNAME.log + +if [ -f /tmp/$DEBNAME_service_runner ]; then + service $DEBNAME start + rm /tmp/$DEBNAME_service_runner fi \ No newline at end of file diff --git a/Lora-Bot/dpkg/preinst b/Lora-Bot/dpkg/preinst index 05a7907..8b6eb86 100644 --- a/Lora-Bot/dpkg/preinst +++ b/Lora-Bot/dpkg/preinst @@ -1,2 +1,6 @@ #!/bin/bash +useradd -M loragwbot +usermod -L loragwbot +groupadd loragwbot +usermod -G loragwbot,adm loragwbot \ No newline at end of file diff --git a/Lora-Bot/dpkg/prerm b/Lora-Bot/dpkg/prerm index 90902f3..e3f281c 100644 --- a/Lora-Bot/dpkg/prerm +++ b/Lora-Bot/dpkg/prerm @@ -1,7 +1,9 @@ #!/bin/bash -if [[ $(systemctl is-active lorabot || true) == "active" ]] +DEBNAME="lorabot" + +if [[ $(systemctl is-active $DEBNAME || true) == "active" ]] then - touch /tmp/lorabot_service_runner - service lorabot stop + touch /tmp/$DEBNAME_service_runner + service $DEBNAME stop fi \ No newline at end of file diff --git a/Lora-Bot/dpkg/lorabot.service b/Lora-Bot/dpkg/service-lorabot similarity index 72% rename from Lora-Bot/dpkg/lorabot.service rename to Lora-Bot/dpkg/service-lorabot index d9e1000..bdaec7e 100644 --- a/Lora-Bot/dpkg/lorabot.service +++ b/Lora-Bot/dpkg/service-lorabot @@ -5,10 +5,10 @@ Description=Lora-Bot After=network-online.target [Service] -User=root -Group=root +User=loragwbot +Group=loragwbot WorkingDirectory=/usr/local/bin/lorabot -ExecStart=/usr/bin/mono /usr/local/bin/lorabot/Lora-Bot.exe +ExecStart=/usr/bin/dotnet /usr/local/bin/lorabot/Lora-Bot.dll KillMode=control-group TimeoutStopSec=5 Restart=on-failure @@ -17,4 +17,4 @@ StandardError=syslog [Install] WantedBy=multi-user.target -Alias=lorabot.service +Alias=lorabot.service \ No newline at end of file diff --git a/doc/Mqttformat.md b/doc/Mqttformat.md index a4aade2..15c8c46 100644 --- a/doc/Mqttformat.md +++ b/doc/Mqttformat.md @@ -1,10 +1,11 @@ -# Lora-Internal-Flow 1.0.0 documentation +# Lora-Gateway-Data 1.1.0 documentation Internal Communication for: * Lora-Gateway * Lora-Map +* Lora-Scral ## Table of Contents @@ -106,7 +107,7 @@ Internal Communication for: - + Topic witch contains the tracking data. @@ -121,8 +122,6 @@ Topic witch contains the tracking data. ##### deviceID -The ID of the streetlight. - @@ -139,10 +138,9 @@ The ID of the streetlight. - - + + @@ -151,6 +149,7 @@ The ID of the streetlight. +
deviceID - - stringstring

The ID of the Tracker

+
Any
@@ -159,7 +158,7 @@ The ID of the streetlight. -### `subscribe` lora/data/{deviceID} +### `publish` lora/data/$deviceID #### Message @@ -192,9 +191,7 @@ Informs you about a Position and Status of a Tracker Bandwidth - - - integer + integer

Bandwidth on witch the Signal was recieved

Any @@ -205,13 +202,12 @@ Informs you about a Position and Status of a Tracker + BatteryLevel - - - number + number

Voltage of the battery from the device

Any @@ -222,13 +218,12 @@ Informs you about a Position and Status of a Tracker + Calculatedcrc - - - integer + integer

The calculated CRC

Any @@ -239,13 +234,12 @@ Informs you about a Position and Status of a Tracker + Codingrate - - - integer + integer

The Codingrate in witch the Signal was recieved

Any @@ -256,13 +250,44 @@ Informs you about a Position and Status of a Tracker + - Crcstatus - + Counter + number +

How many pakets are arrived from the tracker.

+ + Any + + + + + + + + + + + + CorrectInterface + boolean +

If the packet was recieved on the correct interface (eg. to dedect crosstalk)

+ + Any + + + + + + + + - string + + + Crcstatus + string

Shows the CRC-Status in a Field

Ok, Bad, No @@ -273,13 +298,28 @@ Informs you about a Position and Status of a Tracker + - Frequency - + Freqerror + number +

Frequency error that are calculated from the reciever.

+ + Any + + + + + + + + - integer + + + Frequency + integer

The Frequency on that the Message was arrived

Any @@ -290,13 +330,12 @@ Informs you about a Position and Status of a Tracker + Gps - - - object + object

Gps-Data of a Message

Any @@ -305,12 +344,43 @@ Informs you about a Position and Status of a Tracker + Gps.Fix - - - boolean -

Status of the Tracker, true if it has GPS-Signal

+ boolean +

Status of the Tracker, true if it has GPS-Signal.

+ + Any + + + + + + + + + + + + Gps.HasDate + boolean +

If the GPS-Reciever has a valid date.

+ + Any + + + + + + + + + + + + Gps.HasTime + boolean +

If the GPS-Reciever has a valid time.

Any @@ -322,11 +392,10 @@ Informs you about a Position and Status of a Tracker + Gps.Hdop - - - number + number

Dislocation from GPS-Reciever

Any @@ -339,11 +408,10 @@ Informs you about a Position and Status of a Tracker + Gps.Height - - - number + number

Height of the GPS-Reciever

Any @@ -356,12 +424,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastGPSPos - - - string -

Timestamp when the GPS-Reciever has its last position

+ Gps.Latitude + number +

Latitude of the GPS-Reciever

Any @@ -373,12 +440,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastLatitude - - - number -

Last Latitude of the GPS-Reciever

+ Gps.Longitude + number +

Longitude of the GPS-Reciever

Any @@ -390,12 +456,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastLongitude - - - number -

Last Longitude of the GPS-Reciever

+ Gps.Satelites + number +

Amount of satelites that are used for GPS-Positioning

Any @@ -407,12 +472,11 @@ Informs you about a Position and Status of a Tracker + - Gps.Latitude - - - number -

Latitude of the GPS-Reciever

+ Gps.LastGPSPos + string +

[DEPRACED] Timestamp when the GPS-Reciever has its last position

Any @@ -424,12 +488,11 @@ Informs you about a Position and Status of a Tracker + - Gps.Longitude - - - number -

Longitude of the GPS-Reciever

+ Gps.LastLatitude + number +

[DEPRACED] Last Latitude of the GPS-Reciever

Any @@ -441,12 +504,27 @@ Informs you about a Position and Status of a Tracker + + + Gps.LastLongitude + number +

[DEPRACED] Last Longitude of the GPS-Reciever

+ + Any + + + + + + + + + + Gps.Time - - - string -

Timestamp of the GPS-Reciever, that it gets from the Satelites

+ string +

[DEPRACED] Timestamp of the GPS-Reciever, that it gets from the Satelites

Any @@ -460,13 +538,28 @@ Informs you about a Position and Status of a Tracker + - Host - + Hash + string +

A SHA256 hash of the message, to dedect dublicated messages.

+ + Any + + + + + + + + - string + + + Host + string

Name of the Gateway that Recieves the Data

Any @@ -477,13 +570,12 @@ Informs you about a Position and Status of a Tracker + Name - - - string + string

Name of the GPS-Tracker, must be unique between every Device

Any @@ -494,13 +586,12 @@ Informs you about a Position and Status of a Tracker + PacketRssi - - - number + number

Recieve Signal Strength Index for the whole LORA-Messgae

Any @@ -511,13 +602,12 @@ Informs you about a Position and Status of a Tracker + Receivedtime - - - string + string

Timestamp of the Gateway, when it recieves the LORA-Message

Any @@ -528,13 +618,12 @@ Informs you about a Position and Status of a Tracker + Recieverinterface - - - integer + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -545,13 +634,12 @@ Informs you about a Position and Status of a Tracker + Recieverradio - - - integer + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -562,13 +650,12 @@ Informs you about a Position and Status of a Tracker + Rssi - - - number + number

Recieve Signal Strength Index for the LORA-Message

Any @@ -579,13 +666,12 @@ Informs you about a Position and Status of a Tracker + Snr - - - number + number

Signal to Noise Ratio of the LORA-Message

Any @@ -596,13 +682,12 @@ Informs you about a Position and Status of a Tracker + Snrmax - - - number + number

Maximum Signal to Noise Ratio of the LORA-Message

Any @@ -613,13 +698,12 @@ Informs you about a Position and Status of a Tracker + Snrmin - - - number + number

Minimum Signal to Noise Ratio of the LORA-Message

Any @@ -630,13 +714,12 @@ Informs you about a Position and Status of a Tracker + Spreadingfactor - - - integer + integer

The Spreadingfactor of the LORA-Message

Any @@ -647,13 +730,12 @@ Informs you about a Position and Status of a Tracker + Time - - - integer + integer

Internal Timecounter of the LORA-Reciever

Any @@ -664,6 +746,7 @@ Informs you about a Position and Status of a Tracker + @@ -678,19 +761,26 @@ Informs you about a Position and Status of a Tracker "BatteryLevel": 2.5, "Calculatedcrc": 0, "Codingrate": 5, + "Counter": 0, + "CorrectInterface": true, "Crcstatus": "Ok", + "Freqerror": 0, "Frequency": 0, "Gps": { "Fix": true, + "HasDate": true, + "HasTime": true, "Hdop": 0.8, - "Height": 0, + "Height": 42.23, + "Latitude": 50.7, + "Longitude": 7.2, + "Satelites": 4, "LastGPSPos": "01/01/2019 12:00:00", "LastLatitude": 50.7, "LastLongitude": 7.2, - "Latitude": 50.7, - "Longitude": 7.2, "Time": "01/01/2019 12:00:00" }, + "Hash": "string", "Host": "string", "Name": "string", "PacketRssi": 0, @@ -713,7 +803,7 @@ Informs you about a Position and Status of a Tracker - + Topic witch contains the tracking data, when the panic buttons was pressed @@ -728,8 +818,6 @@ Topic witch contains the tracking data, when the panic buttons was pressed ##### deviceID -The ID of the streetlight. - @@ -746,10 +834,9 @@ The ID of the streetlight. - - + + @@ -758,6 +845,7 @@ The ID of the streetlight. +
deviceID - - stringstring

The ID of the Tracker

+
Any
@@ -766,7 +854,7 @@ The ID of the streetlight. -### `subscribe` lora/panic/{deviceID} +### `publish` lora/panic/$deviceID #### Message @@ -799,9 +887,7 @@ Informs you about a Position and Status of a Tracker Bandwidth - - - integer + integer

Bandwidth on witch the Signal was recieved

Any @@ -812,13 +898,12 @@ Informs you about a Position and Status of a Tracker + BatteryLevel - - - number + number

Voltage of the battery from the device

Any @@ -829,13 +914,12 @@ Informs you about a Position and Status of a Tracker + Calculatedcrc - - - integer + integer

The calculated CRC

Any @@ -846,13 +930,12 @@ Informs you about a Position and Status of a Tracker + Codingrate - - - integer + integer

The Codingrate in witch the Signal was recieved

Any @@ -863,13 +946,44 @@ Informs you about a Position and Status of a Tracker + - Crcstatus - + Counter + number +

How many pakets are arrived from the tracker.

+ + Any + + + + + + + + + + + + CorrectInterface + boolean +

If the packet was recieved on the correct interface (eg. to dedect crosstalk)

+ + Any + + + + + + + + - string + + + Crcstatus + string

Shows the CRC-Status in a Field

Ok, Bad, No @@ -880,13 +994,28 @@ Informs you about a Position and Status of a Tracker + - Frequency - + Freqerror + number +

Frequency error that are calculated from the reciever.

+ + Any + + + + + + + + - integer + + + Frequency + integer

The Frequency on that the Message was arrived

Any @@ -897,13 +1026,12 @@ Informs you about a Position and Status of a Tracker + Gps - - - object + object

Gps-Data of a Message

Any @@ -912,12 +1040,43 @@ Informs you about a Position and Status of a Tracker + Gps.Fix - - - boolean -

Status of the Tracker, true if it has GPS-Signal

+ boolean +

Status of the Tracker, true if it has GPS-Signal.

+ + Any + + + + + + + + + + + + Gps.HasDate + boolean +

If the GPS-Reciever has a valid date.

+ + Any + + + + + + + + + + + + Gps.HasTime + boolean +

If the GPS-Reciever has a valid time.

Any @@ -929,11 +1088,10 @@ Informs you about a Position and Status of a Tracker + Gps.Hdop - - - number + number

Dislocation from GPS-Reciever

Any @@ -946,11 +1104,10 @@ Informs you about a Position and Status of a Tracker + Gps.Height - - - number + number

Height of the GPS-Reciever

Any @@ -963,12 +1120,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastGPSPos - - - string -

Timestamp when the GPS-Reciever has its last position

+ Gps.Latitude + number +

Latitude of the GPS-Reciever

Any @@ -980,12 +1136,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastLatitude - - - number -

Last Latitude of the GPS-Reciever

+ Gps.Longitude + number +

Longitude of the GPS-Reciever

Any @@ -997,12 +1152,11 @@ Informs you about a Position and Status of a Tracker + - Gps.LastLongitude - - - number -

Last Longitude of the GPS-Reciever

+ Gps.Satelites + number +

Amount of satelites that are used for GPS-Positioning

Any @@ -1014,12 +1168,11 @@ Informs you about a Position and Status of a Tracker + - Gps.Latitude - - - number -

Latitude of the GPS-Reciever

+ Gps.LastGPSPos + string +

[DEPRACED] Timestamp when the GPS-Reciever has its last position

Any @@ -1031,12 +1184,11 @@ Informs you about a Position and Status of a Tracker + - Gps.Longitude - - - number -

Longitude of the GPS-Reciever

+ Gps.LastLatitude + number +

[DEPRACED] Last Latitude of the GPS-Reciever

Any @@ -1048,12 +1200,27 @@ Informs you about a Position and Status of a Tracker + + + Gps.LastLongitude + number +

[DEPRACED] Last Longitude of the GPS-Reciever

+ + Any + + + + + + + + + + Gps.Time - - - string -

Timestamp of the GPS-Reciever, that it gets from the Satelites

+ string +

[DEPRACED] Timestamp of the GPS-Reciever, that it gets from the Satelites

Any @@ -1067,13 +1234,28 @@ Informs you about a Position and Status of a Tracker + - Host - + Hash + string +

A SHA256 hash of the message, to dedect dublicated messages.

+ + Any + + + + + + + + - string + + + Host + string

Name of the Gateway that Recieves the Data

Any @@ -1084,13 +1266,12 @@ Informs you about a Position and Status of a Tracker + Name - - - string + string

Name of the GPS-Tracker, must be unique between every Device

Any @@ -1101,13 +1282,12 @@ Informs you about a Position and Status of a Tracker + PacketRssi - - - number + number

Recieve Signal Strength Index for the whole LORA-Messgae

Any @@ -1118,13 +1298,12 @@ Informs you about a Position and Status of a Tracker + Receivedtime - - - string + string

Timestamp of the Gateway, when it recieves the LORA-Message

Any @@ -1135,13 +1314,12 @@ Informs you about a Position and Status of a Tracker + Recieverinterface - - - integer + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -1152,13 +1330,12 @@ Informs you about a Position and Status of a Tracker + Recieverradio - - - integer + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -1169,13 +1346,12 @@ Informs you about a Position and Status of a Tracker + Rssi - - - number + number

Recieve Signal Strength Index for the LORA-Message

Any @@ -1186,13 +1362,12 @@ Informs you about a Position and Status of a Tracker + Snr - - - number + number

Signal to Noise Ratio of the LORA-Message

Any @@ -1203,13 +1378,12 @@ Informs you about a Position and Status of a Tracker + Snrmax - - - number + number

Maximum Signal to Noise Ratio of the LORA-Message

Any @@ -1220,13 +1394,12 @@ Informs you about a Position and Status of a Tracker + Snrmin - - - number + number

Minimum Signal to Noise Ratio of the LORA-Message

Any @@ -1237,13 +1410,12 @@ Informs you about a Position and Status of a Tracker + Spreadingfactor - - - integer + integer

The Spreadingfactor of the LORA-Message

Any @@ -1254,13 +1426,12 @@ Informs you about a Position and Status of a Tracker + Time - - - integer + integer

Internal Timecounter of the LORA-Reciever

Any @@ -1271,6 +1442,7 @@ Informs you about a Position and Status of a Tracker + @@ -1285,19 +1457,26 @@ Informs you about a Position and Status of a Tracker "BatteryLevel": 2.5, "Calculatedcrc": 0, "Codingrate": 5, + "Counter": 0, + "CorrectInterface": true, "Crcstatus": "Ok", + "Freqerror": 0, "Frequency": 0, "Gps": { "Fix": true, + "HasDate": true, + "HasTime": true, "Hdop": 0.8, - "Height": 0, + "Height": 42.23, + "Latitude": 50.7, + "Longitude": 7.2, + "Satelites": 4, "LastGPSPos": "01/01/2019 12:00:00", "LastLatitude": 50.7, "LastLongitude": 7.2, - "Latitude": 50.7, - "Longitude": 7.2, "Time": "01/01/2019 12:00:00" }, + "Hash": "string", "Host": "string", "Name": "string", "PacketRssi": 0, @@ -1320,7 +1499,7 @@ Informs you about a Position and Status of a Tracker - + Topic witch contains status of the devices @@ -1335,8 +1514,6 @@ Topic witch contains status of the devices ##### deviceID -The ID of the streetlight. - @@ -1353,10 +1530,9 @@ The ID of the streetlight. - - + + @@ -1365,6 +1541,7 @@ The ID of the streetlight. +
deviceID - - stringstring

The ID of the Tracker

+
Any
@@ -1373,7 +1550,7 @@ The ID of the streetlight. -### `subscribe` lora/status/{deviceID} +### `publish` lora/status/$deviceID #### Message @@ -1406,9 +1583,7 @@ Informs you about a Status of a Tracker Bandwidth - - - integer + integer

Bandwidth on witch the Signal was recieved

Any @@ -1419,13 +1594,12 @@ Informs you about a Status of a Tracker + BatteryLevel - - - number + number

Voltage of the battery from the device

Any @@ -1436,13 +1610,12 @@ Informs you about a Status of a Tracker + Calculatedcrc - - - integer + integer

The calculated CRC

Any @@ -1453,13 +1626,12 @@ Informs you about a Status of a Tracker + Codingrate - - - integer + integer

The Codingrate in witch the Signal was recieved

Any @@ -1470,13 +1642,28 @@ Informs you about a Status of a Tracker + - Crcstatus - + CorrectInterface + boolean +

If the packet was recieved on the correct interface (eg. to dedect crosstalk)

+ + Any + + + + + + + + - string + + + Crcstatus + string

Shows the CRC-Status in a Field

Ok, Bad, No @@ -1487,13 +1674,12 @@ Informs you about a Status of a Tracker + DeviceStatus - - - string + string

Shows the internal state in a Field

Startup, Powersave, Shutdown @@ -1504,13 +1690,28 @@ Informs you about a Status of a Tracker + - Frequency - + Freqerror + number +

Frequency error that are calculated from the reciever.

+ + Any + + + + + + + + - integer + + + Frequency + integer

The Frequency on that the Message was arrived

Any @@ -1521,13 +1722,12 @@ Informs you about a Status of a Tracker + FrequencyOffset - - - integer + integer

The internal offset to the base frequency, to compensate cheap china rf modules

Any @@ -1538,13 +1738,28 @@ Informs you about a Status of a Tracker + - Host - + Hash + string +

A SHA256 hash of the message, to dedect dublicated messages.

+ + Any + + + + + + + + - string + + + Host + string

Name of the Gateway that Recieves the Data

Any @@ -1555,13 +1770,12 @@ Informs you about a Status of a Tracker + IpAddress - - - string + string

IP-Address of the device, for debug

Any @@ -1572,13 +1786,12 @@ Informs you about a Status of a Tracker + Name - - - string + string

Name of the GPS-Tracker, must be unique between every Device

Any @@ -1589,13 +1802,12 @@ Informs you about a Status of a Tracker + PacketRssi - - - number + number

Recieve Signal Strength Index for the whole LORA-Messgae

Any @@ -1606,13 +1818,12 @@ Informs you about a Status of a Tracker + Receivedtime - - - string + string

Timestamp of the Gateway, when it recieves the LORA-Message

Any @@ -1623,13 +1834,12 @@ Informs you about a Status of a Tracker + Recieverinterface - - - integer + integer

Internal virtual Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -1640,13 +1850,12 @@ Informs you about a Status of a Tracker + Recieverradio - - - integer + integer

Internal Radio of the Gateway, witch recieves the LORA-Messange

Any @@ -1657,13 +1866,12 @@ Informs you about a Status of a Tracker + Rssi - - - number + number

Recieve Signal Strength Index for the LORA-Message

Any @@ -1674,13 +1882,12 @@ Informs you about a Status of a Tracker + Snr - - - number + number

Signal to Noise Ratio of the LORA-Message

Any @@ -1691,13 +1898,12 @@ Informs you about a Status of a Tracker + Snrmax - - - number + number

Maximum Signal to Noise Ratio of the LORA-Message

Any @@ -1708,13 +1914,12 @@ Informs you about a Status of a Tracker + Snrmin - - - number + number

Minimum Signal to Noise Ratio of the LORA-Message

Any @@ -1725,13 +1930,12 @@ Informs you about a Status of a Tracker + Spreadingfactor - - - integer + integer

The Spreadingfactor of the LORA-Message

Any @@ -1742,13 +1946,12 @@ Informs you about a Status of a Tracker + Time - - - integer + integer

Internal Timecounter of the LORA-Reciever

Any @@ -1759,13 +1962,12 @@ Informs you about a Status of a Tracker + Version - - - integer + integer

Software-Versionsnumber of the Device

Any @@ -1776,13 +1978,12 @@ Informs you about a Status of a Tracker + WifiActive - - - boolean + boolean

Status if the Device successufly connect to a wifi

Any @@ -1793,13 +1994,12 @@ Informs you about a Status of a Tracker + WifiSsid - - - string + string

SSID of the WIFI witch the device connects to.

Any @@ -1810,6 +2010,7 @@ Informs you about a Status of a Tracker + @@ -1824,10 +2025,13 @@ Informs you about a Status of a Tracker "BatteryLevel": 2.5, "Calculatedcrc": 0, "Codingrate": 5, + "CorrectInterface": true, "Crcstatus": "Ok", "DeviceStatus": "Startup", + "Freqerror": 0, "Frequency": 0, "FrequencyOffset": 0, + "Hash": "string", "Host": "string", "IpAddress": "0.0.0.0", "Name": "string", diff --git a/doc/Mqttformat.yml b/doc/Mqttformat.yml new file mode 100644 index 0000000..0d0e230 --- /dev/null +++ b/doc/Mqttformat.yml @@ -0,0 +1,349 @@ +asyncapi: 2.0.0 +info: + title: Lora-Gateway-Data + version: '1.1.0' + description: | + Internal Communication for: + * Lora-Gateway + * Lora-Map + * Lora-Scral + license: + name: LGPL3 + url: http://www.gnu.org/licenses/lgpl-3.0.html + +servers: + production: + url: 127.0.0.1:{port} + protocol: mqtt + description: Lora-Broker + security: + - userPassword: [] + variables: + port: + description: Secure connection (TLS) is available through port 8883. + default: '1883' + enum: + - '1883' + - '8883' + +defaultContentType: application/json + +channels: + lora/data/$deviceID: + description: Topic witch contains the tracking data. + parameters: + deviceID: + $ref: '#/components/parameters/deviceID' + publish: + operationId: loradata + message: + $ref: '#/components/messages/loradata' + + + lora/panic/$deviceID: + description: Topic witch contains the tracking data, when the panic buttons was pressed + parameters: + deviceID: + $ref: '#/components/parameters/deviceID' + publish: + operationId: lorapanic + message: + $ref: '#/components/messages/loradata' + + + lora/status/$deviceID: + description: Topic witch contains status of the devices + parameters: + deviceID: + $ref: '#/components/parameters/deviceID' + publish: + operationId: lorastatus + message: + $ref: '#/components/messages/lorastatus' + +components: + messages: + loradata: + name: trackerData + title: Positionsdata + summary: Informs you about a Position and Status of a Tracker + contentType: application/json + payload: + $ref: "#/components/schemas/loradataPayload" + lorastatus: + name: loraStatus + title: Statusdata + summary: Informs you about a Status of a Tracker + payload: + $ref: "#/components/schemas/lorastausPayload" + + schemas: + loradataPayload: + $ref: "#/components/schemas/loradataObject" + + lorastausPayload: + $ref: "#/components/schemas/lorastatusObject" + + loradataObject: + type: object + required: + - BatteryLevel + - Gps + - Name + properties: + Bandwidth: + type: integer + description: Bandwidth on witch the Signal was recieved + minimum: 7800 + maximum: 500000 + BatteryLevel: + type: number + description: Voltage of the battery from the device + minimum: 2.5 + maximum: 5 + Calculatedcrc: + type: integer + description: The calculated CRC + Codingrate: + type: integer + description: The Codingrate in witch the Signal was recieved + minimum: 5 + maximum: 8 + Counter: + type: number + description: How many pakets are arrived from the tracker. + CorrectInterface: + type: boolean + description: If the packet was recieved on the correct interface (eg. to dedect crosstalk) + Crcstatus: + type: string + description: Shows the CRC-Status in a Field + enum: + - Ok + - Bad + - No + Freqerror: + type: number + description: Frequency error that are calculated from the reciever. + Frequency: + type: integer + description: The Frequency on that the Message was arrived + Gps: + type: object + description: Gps-Data of a Message + required: + - Fix + - Height + - Latitude + - Longitude + properties: + Fix: + type: boolean + description: Status of the Tracker, true if it has GPS-Signal. + HasDate: + type: boolean + description: If the GPS-Reciever has a valid date. + HasTime: + type: boolean + description: If the GPS-Reciever has a valid time. + Hdop: + type: number + description: Dislocation from GPS-Reciever + minimum: 0.8 + maximum: 25 + Height: + type: number + description: Height of the GPS-Reciever + default: 42.23 + Latitude: + type: number + description: Latitude of the GPS-Reciever + default: 50.7 + Longitude: + type: number + description: Longitude of the GPS-Reciever + default: 7.2 + Satelites: + type: number + description: Amount of satelites that are used for GPS-Positioning + default: 4 + LastGPSPos: + type: string + description: \[DEPRACED] Timestamp when the GPS-Reciever has its last position + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + LastLatitude: + type: number + description: \[DEPRACED] Last Latitude of the GPS-Reciever + default: 50.7 + LastLongitude: + type: number + description: \[DEPRACED] Last Longitude of the GPS-Reciever + default: 7.2 + Time: + type: string + description: \[DEPRACED] Timestamp of the GPS-Reciever, that it gets from the Satelites + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + Hash: + type: string + description: A SHA256 hash of the message, to dedect dublicated messages. + Host: + type: string + description: Name of the Gateway that Recieves the Data + Name: + type: string + description: Name of the GPS-Tracker, must be unique between every Device + format: "/[a-z]{2}/i" + PacketRssi: + type: number + description: Recieve Signal Strength Index for the whole LORA-Messgae + Receivedtime: + type: string + description: Timestamp of the Gateway, when it recieves the LORA-Message + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + Recieverinterface: + type: integer + description: Internal virtual Radio of the Gateway, witch recieves the LORA-Messange + Recieverradio: + type: integer + description: Internal Radio of the Gateway, witch recieves the LORA-Messange + Rssi: + type: number + description: Recieve Signal Strength Index for the LORA-Message + Snr: + type: number + description: Signal to Noise Ratio of the LORA-Message + Snrmax: + type: number + description: Maximum Signal to Noise Ratio of the LORA-Message + Snrmin: + type: number + description: Minimum Signal to Noise Ratio of the LORA-Message + Spreadingfactor: + type: integer + description: The Spreadingfactor of the LORA-Message + minimum: 7 + maximum: 12 + Time: + type: integer + description: Internal Timecounter of the LORA-Reciever + + lorastatusObject: + type: object + properties: + Bandwidth: + type: integer + description: Bandwidth on witch the Signal was recieved + minimum: 7800 + maximum: 500000 + BatteryLevel: + type: number + description: Voltage of the battery from the device + minimum: 2.5 + maximum: 5 + Calculatedcrc: + type: integer + description: The calculated CRC + Codingrate: + type: integer + description: The Codingrate in witch the Signal was recieved + minimum: 5 + maximum: 8 + CorrectInterface: + type: boolean + description: If the packet was recieved on the correct interface (eg. to dedect crosstalk) + Crcstatus: + type: string + description: Shows the CRC-Status in a Field + enum: + - Ok + - Bad + - No + DeviceStatus: + type: string + description: Shows the internal state in a Field + enum: + - Startup + - Powersave + - Shutdown + Freqerror: + type: number + description: Frequency error that are calculated from the reciever. + Frequency: + type: integer + description: The Frequency on that the Message was arrived + FrequencyOffset: + type: integer + description: The internal offset to the base frequency, to compensate cheap china rf modules + Hash: + type: string + description: A SHA256 hash of the message, to dedect dublicated messages. + Host: + type: string + description: Name of the Gateway that Recieves the Data + IpAddress: + type: string + description: IP-Address of the device, for debug + default: "0.0.0.0" + format: "[0-9]\\.[0-9]\\.[0-9]\\.[0-9]" + Name: + type: string + description: Name of the GPS-Tracker, must be unique between every Device + format: "/[a-z]{2}/i" + PacketRssi: + type: number + description: Recieve Signal Strength Index for the whole LORA-Messgae + Receivedtime: + type: string + description: Timestamp of the Gateway, when it recieves the LORA-Message + format: dd/mm/YYYY hh:MM:ss + default: 01/01/2019 12:00:00 + Recieverinterface: + type: integer + description: Internal virtual Radio of the Gateway, witch recieves the LORA-Messange + Recieverradio: + type: integer + description: Internal Radio of the Gateway, witch recieves the LORA-Messange + Rssi: + type: number + description: Recieve Signal Strength Index for the LORA-Message + Snr: + type: number + description: Signal to Noise Ratio of the LORA-Message + Snrmax: + type: number + description: Maximum Signal to Noise Ratio of the LORA-Message + Snrmin: + type: number + description: Minimum Signal to Noise Ratio of the LORA-Message + Spreadingfactor: + type: integer + description: The Spreadingfactor of the LORA-Message + minimum: 7 + maximum: 12 + Time: + type: integer + description: Internal Timecounter of the LORA-Reciever + Version: + type: integer + description: Software-Versionsnumber of the Device + WifiActive: + type: boolean + description: Status if the Device successufly connect to a wifi + WifiSsid: + type: string + description: SSID of the WIFI witch the device connects to. + + securitySchemes: + userPassword: + type: userPassword + description: Using Username and Password to connect to online broker + + parameters: + deviceID: + schema: + type: string + description: The ID of the Tracker + format: "[A-Z]{2}" From 50e59506d7fcc588fa5d398f58ee23171cda5a89 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 18 Jan 2020 00:22:05 +0100 Subject: [PATCH 24/29] Packet was not installable on raspi --- .github/workflows/dotnetcore.yml | 2 +- Lora-Bot/dpkg/control | 2 +- Lora-Bot/dpkg/postinst | 2 ++ Lora-Bot/dpkg/preinst | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index 646e1a1..b0e5923 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -47,7 +47,7 @@ jobs: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: tag_name: ${{ steps.create_deb.outputs.builddaterelease }} - release_name: Nightly from master + release_name: Nightly from ${{ steps.create_deb.outputs.builddaterelease }} body: This is a nightly release. It may be not working properly. draft: false prerelease: true diff --git a/Lora-Bot/dpkg/control b/Lora-Bot/dpkg/control index bb17d45..d2f0bbc 100644 --- a/Lora-Bot/dpkg/control +++ b/Lora-Bot/dpkg/control @@ -3,7 +3,7 @@ Version: x.x-x Section: base Priority: optional Architecture: any -Depends: wiringpi (>= 2.50), dotnet-runtime-3.0 (>= 3.0.1) +Depends: wiringpi (>= 2.50) Maintainer: BlubbFish Description: Lora-Bot Lora-Bot is a Lora gateway diff --git a/Lora-Bot/dpkg/postinst b/Lora-Bot/dpkg/postinst index bbbc6b4..28d8c64 100644 --- a/Lora-Bot/dpkg/postinst +++ b/Lora-Bot/dpkg/postinst @@ -9,6 +9,8 @@ touch /var/log/$DEBNAME.log chown loragwbot:loragwbot /var/log/$DEBNAME.log chmod 644 /var/log/$DEBNAME.log +chown -R loragwbot:loragwbot /usr/local/bin/$DEBNAME + if [ -f /tmp/$DEBNAME_service_runner ]; then service $DEBNAME start rm /tmp/$DEBNAME_service_runner diff --git a/Lora-Bot/dpkg/preinst b/Lora-Bot/dpkg/preinst index 8b6eb86..32e2095 100644 --- a/Lora-Bot/dpkg/preinst +++ b/Lora-Bot/dpkg/preinst @@ -3,4 +3,4 @@ useradd -M loragwbot usermod -L loragwbot groupadd loragwbot -usermod -G loragwbot,adm loragwbot \ No newline at end of file +usermod -G loragwbot,adm,gpio,spi loragwbot \ No newline at end of file From 6cbf597e54fb3c9c4e53561416b134ac26708966 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Sat, 18 Jan 2020 10:45:20 +0100 Subject: [PATCH 25/29] Update README.md --- Lora-Bot.sln | 8 ++++++++ README.md | 20 -------------------- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/Lora-Bot.sln b/Lora-Bot.sln index f48f9a3..6722fd8 100644 --- a/Lora-Bot.sln +++ b/Lora-Bot.sln @@ -29,6 +29,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.RaspberryIO", ".. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Unosquare.WiringPi", "..\Librarys\RaspberryIO_26\Unosquare.WiringPi\Unosquare.WiringPi.csproj", "{037664CC-0F00-4DFE-AD5F-19AF2DE3431F}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{61C25DCC-8804-4435-A1E8-EC997CED8762}" + ProjectSection(SolutionItems) = preProject + ..\CONTRIBUTING.md = ..\CONTRIBUTING.md + ..\LICENSE = ..\LICENSE + ..\README.md = ..\README.md + ..\update.sh = ..\update.sh + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/README.md b/README.md index ae97f5c..e793a11 100644 --- a/README.md +++ b/README.md @@ -38,26 +38,6 @@ This projects depends on some librarys: * Unosquare RaspberryIO * Unosquare WiringPI - -### Test - -The only way to test this programm is to run it on real hardware. - - -### Build - -Please build it with Visual Studio. - -To install dotnet on a Raspi: -* [Download .NET Core Runtime 3.1.0](https://dotnet.microsoft.com/download/dotnet-core/3.1) for ARM32 -```bash -wget [download link] -sudo mkdir /usr/share/dotnet -sudo tar zxf dotnet-runtime-3.1.0-linux-arm.tar.gz -C /usr/share/dotnet -rm dotnet-runtime-3.1.0-linux-arm.tar.gz -sudo ln -s /usr/share/dotnet/dotnet /usr/bin/dotnet -``` - ## Contributing Contributions are welcome. From cc2e2b9daa65b8bde4e31e846b664bc2ffe46f82 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Mon, 20 Jan 2020 11:45:35 +0100 Subject: [PATCH 26/29] Remove some depraced stuff --- Lora-Bot/Events/GpsUpdateEvent.cs | 23 +-- Lora-Bot/Models/BinaryPacket.cs | 8 +- Lora-Bot/Models/GpsInfo.cs | 88 ---------- Lora-Bot/Models/Tracker.cs | 259 ------------------------------ Lora-Bot/Parser/LoraParser.cs | 21 +-- 5 files changed, 3 insertions(+), 396 deletions(-) delete mode 100644 Lora-Bot/Models/GpsInfo.cs delete mode 100644 Lora-Bot/Models/Tracker.cs diff --git a/Lora-Bot/Events/GpsUpdateEvent.cs b/Lora-Bot/Events/GpsUpdateEvent.cs index 8317875..838a529 100644 --- a/Lora-Bot/Events/GpsUpdateEvent.cs +++ b/Lora-Bot/Events/GpsUpdateEvent.cs @@ -15,7 +15,6 @@ public Boolean HasTime { get; set; } - public Double Hdop { get; set; } @@ -37,26 +36,6 @@ public Byte Satelites { } #endregion - [Obsolete("Should do by client")] - public Double LastLatitude { - get; set; - } - [Obsolete("Should do by client")] - public Double LastLongitude { - get; set; - } - [Obsolete("Should do by client")] - public DateTime LastGPSPos { - get; set; - } - - [Obsolete("Will be not Transmitted anymore")] - public DateTime Time { - get; set; - } - - public override String ToString() => "Lat: " + this.Latitude + " [" + this.LastLatitude + "] Lon: " + this.Longitude + " [" + this.LastLongitude + "] Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; - - //public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- Time: " + this.Time + " HDOP: " + this.Hdop + " Fix: " + this.Fix; + public override String ToString() => "Lat: " + this.Latitude + " Lon: " + this.Longitude + " Height: " + this.Height + " -- HDOP: " + this.Hdop + " Satelites: " + this.Satelites + " Fix: [" + (this.HasTime ? "t" : "x") + "," + (this.HasDate ? "d" : "x") + "," + (this.Fix ? "f" : "x") + "]"; } } diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs index 9587751..5dfec2a 100644 --- a/Lora-Bot/Models/BinaryPacket.cs +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -6,7 +6,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class BinaryPacket : Packet { - public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, DateTime date, Single battery, RecievedData recieveddata, Tuple old) { + public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, RecievedData recieveddata) { this.TransferData = new LocationUpdateEvent(typ) { Name = name, BatteryLevel = battery, @@ -15,17 +15,11 @@ public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Sin Longitude = lon, Hdop = hdop, Height = height, - Time = date, Fix = lat != 0 || lon != 0 } }; this.Type = typ; this.SetLoraData(recieveddata, this.TransferData); - if(typ == LoraParser.Typ.Data) { - this.TransferData.Gps.LastLatitude = old.Item1; - this.TransferData.Gps.LastLongitude = old.Item2; - this.TransferData.Gps.LastGPSPos = old.Item3; - } } public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, UInt16 counter, Boolean has_time, Boolean has_date, Boolean has_fix, Byte sat, Boolean correct_if, String hash, RecievedData recieveddata) { diff --git a/Lora-Bot/Models/GpsInfo.cs b/Lora-Bot/Models/GpsInfo.cs deleted file mode 100644 index 1d99111..0000000 --- a/Lora-Bot/Models/GpsInfo.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; - -namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { - /*public class GpsInfo { - public Double Latitude { - get; private set; - } - public Double LastLatitude { - get; private set; - } - public Double Longitude { - get; private set; - } - public Double LastLongitude { - get; private set; - } - public DateTime LastGPSPos { - get; private set; - } - public DateTime Time { - get; private set; - } - public Double Hdop { - get; private set; - } - public Boolean Fix { - get; private set; - } - public Double Height { - get; private set; - } - - public GpsInfo() { - this.Latitude = 0; - this.LastLatitude = 0; - this.Latitude = 0; - this.LastLongitude = 0; - this.Time = DateTime.MinValue; - this.Hdop = 99; - this.Fix = false; - this.Height = 0; - } - - public void SetUpdate(String str) { - String[] infos = str.Split(','); - - if(Double.TryParse(infos[0], out Double breitengrad)) { - this.Latitude = breitengrad; - } - if(Double.TryParse(infos[1], out Double laengengrad)) { - this.Longitude = laengengrad; - } - String d = DateTime.UtcNow.Day + "." + DateTime.UtcNow.Month + "." + DateTime.UtcNow.Year + " " + infos[2][0] + infos[2][1] + ":" + infos[2][2] + infos[2][3] + ":" + infos[2][4] + infos[2][5]; - if(DateTime.TryParse(d, out DateTime dv)) { - this.Time = dv; - } - if(Double.TryParse(infos[3], out Double hdop)) { - this.Hdop = hdop; - } - if(Double.TryParse(infos[4], out Double height)) { - this.Height = height; - } - this.Fix = !(Math.Abs(this.Latitude) < 0.000001 && Math.Abs(this.Longitude) < 0.000001); //Check for 0 lat and long - if(this.Fix) { - this.LastLongitude = this.Longitude; - this.LastLatitude = this.Latitude; - this.LastGPSPos = DateTime.UtcNow; - } - } - - public void SetUpdate(Single lat, Single lon, Single height, Single hdop, Byte hour, Byte minute, Byte second, Byte day, Byte month, UInt16 year) { - this.Latitude = lat; - this.Longitude = lon; - this.Height = height; - String d = day.ToString().PadLeft(2, '0') + "." + month.ToString().PadLeft(2, '0') + "." + year.ToString().PadLeft(4, '0') + " " + hour.ToString().PadLeft(2, '0') + ":" + minute.ToString().PadLeft(2, '0') + ":" + second.ToString().PadLeft(2, '0'); - if(DateTime.TryParse(d, out DateTime dv)) { - this.Time = dv; - } - this.Hdop = hdop; - this.Fix = lat != 0 && lon != 0; - if(this.Fix) { - this.LastLongitude = this.Longitude; - this.LastLatitude = this.Latitude; - this.LastGPSPos = DateTime.UtcNow; - } - } - }*/ -} diff --git a/Lora-Bot/Models/Tracker.cs b/Lora-Bot/Models/Tracker.cs deleted file mode 100644 index 6fc1279..0000000 --- a/Lora-Bot/Models/Tracker.cs +++ /dev/null @@ -1,259 +0,0 @@ -using System; -using System.Text.RegularExpressions; - -using Fraunhofer.Fit.Iot.Lora.Events; -using Fraunhofer.Fit.IoT.Bots.LoraBot.Events; - -namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { - /*public class Tracker { - private enum ParseType { - Update, - Panic - } - - public delegate void UpdateDataEvent(Object sender, DataUpdateEvent e); - public delegate void UpdatePanicEvent(Object sender, PanicUpdateEvent e); - public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); - public event UpdateDataEvent DataUpdate; - public event UpdatePanicEvent PanicUpdate; - public event UpdateStatusEvent StatusUpdate; - - public Int32 Bandwidth { - get; private set; - } - public Double BatteryLevel { - get; private set; - } - public UInt16 CalculatedCRC { - get; private set; - } - public Byte CodingRate { - get; private set; - } - public String CRCStatus { - get; private set; - } - public Status DeviceStatus { - get; private set; - } - public UInt32 Frequency { - get; private set; - } - public Int32 FrequencyOffset { - get; private set; - } - public GpsInfo Gps { - get; private set; - } - public String IpAddress { - get; private set; - } - public String Modulation { - get; private set; - } - public String Name { - get; private set; - } - public Double PacketRssi { - get; private set; - } - public Byte RecieverInterface { - get; private set; - } - public Byte RecieverRadio { - get; private set; - } - public DateTime ReceivedTime { - get; private set; - } - public Double Rssi { - get; private set; - } - public Double Snr { - get; private set; - } - public Double SnrMax { - get; private set; - } - public Double SnrMin { - get; private set; - } - public Byte SpreadingFactor { - get; private set; - } - public UInt32 Time { - get; private set; - } - public Int32 Version { - get; private set; - } - public Boolean WifiActive { - get; private set; - } - public String WifiSsid { - get; private set; - } - - public enum Status { - Unknown, - Startup, - Powersave, - Shutdown - } - - public Tracker() => this.Gps = new GpsInfo(); - - #region Private Parsers and Helpers - private void Parse(Byte[] data, ParseType dataType) { - if(data.Length == 21) { - this.Name = GetName(data); - Single lat = BitConverter.ToSingle(data, 3); - Single lon = BitConverter.ToSingle(data, 7); - Single hdop = (Single)data[11] / 10; - Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; - Byte hour = data[14]; - Byte minute = data[15]; - Byte second = data[16]; - Byte day = data[17]; - Byte month = data[18]; - UInt16 year = (UInt16)(data[19] + 2000); - this.BatteryLevel = ((Single)data[20] + 230) / 100; - this.Gps.SetUpdate(lat, lon, height, hdop, hour, minute, second, day, month, year); - //Console.WriteLine("lat: " + lat + " lon: " + lon + " hdop: " + hdop + " heigt: " + height + " hh:mm:ss: " + hour + ":" + minute + ":" + second + " DD.MM.YY: " + day + "." + month + "." + year + " bat: " + this.BatteryLevel); - if(dataType == ParseType.Panic) { - this.PanicUpdate?.Invoke(this, new PanicUpdateEvent(this)); - } - this.DataUpdate?.Invoke(this, new DataUpdateEvent(this)); - } - } - - private void Parse(String text) { - String[] texts = text.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); - this.Name = GetName(text, 0); - String[] infos = texts[1].Split(','); - if(infos.Length >= 6 && Double.TryParse(infos[5], out Double batteryLevel)) { - this.BatteryLevel = batteryLevel; - } - this.Gps.SetUpdate(texts[1]); - this.DataUpdate?.Invoke(this, new DataUpdateEvent(this)); - } - - private void ParseStatus(String text) { - String[] texts = text.Split(new String[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); - if(texts.Length != 3) { - return; - } - this.Name = GetName(text, 1); - String[] infos = texts[2].Split(','); - if(infos.Length != 7) { - return; - } - if(Int32.TryParse(infos[0], out Int32 version)) { - this.Version = version; - } - this.IpAddress = infos[1]; - this.WifiSsid = infos[2]; - this.WifiActive = infos[3] == "t"; - if(Double.TryParse(infos[4], out Double batteryLevel)) { - this.BatteryLevel = batteryLevel; - } - if(Int32.TryParse(infos[5], out Int32 freqOffset)) { - this.FrequencyOffset = freqOffset; - } - if(Int32.TryParse(infos[6], out Int32 deviceStatus)) { - if(deviceStatus == 0) { - this.DeviceStatus = Status.Shutdown; - } else if(deviceStatus == 1) { - this.DeviceStatus = Status.Startup; - } else if(deviceStatus == 2) { - this.DeviceStatus = Status.Powersave; - } - } - this.StatusUpdate?.Invoke(this, new StatusUpdateEvent(this)); - } - - private void SetUpdate(LoraClientEvent e) { - if(e is Ic800ALoraClientEvent) { - Ic800ALoraClientEvent ic = e as Ic800ALoraClientEvent; - this.Bandwidth = ic.Bandwidth; - this.CalculatedCRC = ic.Calculatedcrc; - this.CodingRate = ic.CodingRate; - this.CRCStatus = ic.CrcStatus; - this.Frequency = ic.Frequency; - this.RecieverInterface = ic.Interface; - this.Modulation = ic.Modulation; - this.RecieverRadio = ic.Radio; - this.SnrMax = ic.SnrMax; - this.SnrMin = ic.SnrMin; - this.SpreadingFactor = ic.Spreadingfactor; - this.Time = ic.Time; - } - this.PacketRssi = e.Packetrssi; - this.Rssi = e.Rssi; - this.Snr = e.Snr; - this.ReceivedTime = e.UpdateTime; - } - #endregion - - #region External update Methods - public void SetUpdate(LoraClientEvent e, String data) { - this.SetUpdate(e); - this.Parse(data); - } - - public void SetUpdate(LoraClientEvent e, Byte[] data) { - this.SetUpdate(e); - this.Parse(data, ParseType.Update); - } - public void SetPanics(LoraClientEvent e, Byte[] data) { - this.SetUpdate(e); - this.Parse(data, ParseType.Panic); - } - - public void SetStatus(LoraClientEvent e, String textStatus) { - this.SetUpdate(e); - this.ParseStatus(textStatus); - } - #endregion - - #region Static Functions - public static Boolean CheckPacket(String message) { - String[] m; - if(message.Contains("\r\n")) { - m = message.Split(new String[] { "\r\n" }, StringSplitOptions.None); - } else if(message.Contains("\n")) { - m = message.Split(new String[] { "\n" }, StringSplitOptions.None); - } else { - return false; - } - if(m.Length == 2) { //Normal Data Packet - return m[0] == "" ? false : Regex.Match(m[1], "[0-9]+.[0-9]{5,10},[0-9]+.[0-9]{5,10},[0-9]{6},[0-9]+.[0-9]{2},[0-9]+.[0-9],[0-9].[0-9]{2}").Success; - } - if(m.Length == 3) { //Debug Packet - if(m[0] != "deb") { //first must be "deb" - return false; - } - if(m[1] == "") { //Name should not be empty - return false; - } - //version,ip,ssid,wififlag,battery,offset,statusmode - return Regex.Match(m[2], "^[0-9]+,[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3},[^,]+,[tf],[0-9].[0-9]{2},(-[0-9]+|[0-9]+),[0-9]").Success; - } - return false; - } - - public static String GetName(String message, Int32 index) => message.Contains("\r\n") ? message.Split(new String[] { "\r\n" }, StringSplitOptions.None)[index].Trim() : message.Contains("\n") ? message.Split(new String[] { "\n" }, StringSplitOptions.None)[index].Trim() : ""; - - public static String GetName(Byte[] data) { - if(data.Length >= 3) { - Byte[] ret = new Byte[2]; - for(Int32 i = 0; i < 2; i++) { - ret[i] = data[i + 1]; - } - return ret[1] == 0 ? System.Text.Encoding.ASCII.GetString(new Byte[] { ret[0] }).Trim() : System.Text.Encoding.ASCII.GetString(ret).Trim(); - } - return ""; - } - #endregion - }*/ -} diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index ab94b7a..ee45d46 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -27,9 +27,6 @@ public LoraParser(String key) { this.CryptoKey = k; } - private readonly SortedDictionary> oldmarkerpos = new SortedDictionary>(); - private readonly Object oldmarkerposlock = new Object(); - public delegate void UpdateDataEvent(Object sender, LocationUpdateEvent e); public delegate void UpdatePanicEvent(Object sender, LocationUpdateEvent e); public delegate void UpdateStatusEvent(Object sender, StatusUpdateEvent e); @@ -162,24 +159,8 @@ private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { Single lon = BitConverter.ToSingle(data, 7); Single hdop = (Single)data[11] / 10; Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; - DateTime date = DateTime.TryParse(data[17].ToString().PadLeft(2, '0') + "." + data[18].ToString().PadLeft(2, '0') + "." + ((UInt16)(data[19] + 2000)).ToString().PadLeft(4, '0') + " " + data[14].ToString().PadLeft(2, '0') + ":" + data[15].ToString().PadLeft(2, '0') + ":" + data[16].ToString().PadLeft(2, '0'), out DateTime dv) ? dv : DateTime.MinValue; Single battery = ((Single)data[20] + 230) / 100; - Tuple old = new Tuple(0, 0, DateTime.MinValue); - if(lat != 0 || lon != 0) { - lock(this.oldmarkerposlock) { - if(this.oldmarkerpos.ContainsKey(name)) { - this.oldmarkerpos[name] = new Tuple(lat, lon, DateTime.Now); - } else { - this.oldmarkerpos.Add(name, new Tuple(lat, lon, DateTime.Now)); - } - } - } - lock(this.oldmarkerpos) { - if(this.oldmarkerpos.ContainsKey(name)) { - old = this.oldmarkerpos[name]; - } - } - return new BinaryPacket(name, typ, lat, lon, hdop, height, date, battery, recieveddata, old); + return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, recieveddata); } else if(data.Length == 18) { UInt16 counter = BitConverter.ToUInt16(data, 0); String name = data[3] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[2] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[3] }).Trim(); From cafd3a7ea183dba7ff40b65263dcf266caf053f8 Mon Sep 17 00:00:00 2001 From: BlubbFish Date: Tue, 21 Jan 2020 21:27:03 +0100 Subject: [PATCH 27/29] Parsing battery in status packet now works with InvariantCulture Round the values height, battery and hdop now to its calculated values Only understand the binaryformat from version 16 --- CHANGELOG.md | 5 ++- Lora-Bot/Lora-Bot.csproj | 48 +++++++++++++------------ Lora-Bot/Models/BinaryPacket.cs | 18 +--------- Lora-Bot/Parser/LoraParser.cs | 63 +++++++++------------------------ 4 files changed, 47 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8763195..7db24c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,17 +2,20 @@ ## 2.0.0 - The total rewrite ### New Features - * Add Github Actions * Parsing data is now in this software part * Add new fileds in json * Documenting the Binary transmission ### Bugfixes +* Parsing battery in status packet now works with InvariantCulture + ### Changes * Debugging will be done over configure file * Refactoring * Porting to .NET Core +* Round the values height, battery and hdop now to its calculated values +* Only understand the binaryformat from version 16 ## 1.8.4 ### New Features diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index 691cee9..845c931 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -15,26 +15,28 @@ https://github.com/MONICA-Project/lora-bot https://github.com/MONICA-Project/lora-bot.git git - 2.0.0 The total rewrite -1.8.4 Fixing a bug related to threaded working with data -1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend -1.8.2 Bugfix, create also an event for sending normal loradata when update panic -1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved -1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC -1.7.3 Parsing new Status format and Panic Package -1.7.2 Update to local librarys -1.7.1 Fixing binary data transmission & fixing Scral Plugin -1.7.0 Adding IC800A Lora-Reciever -1.6.2 Adding a test for LoraBinary -1.6.1 Fixing parsing bug with linebreaks in Lora -1.6.0 Implement Height in LoraBot -1.5.1 Dependencies in debian Packet cleaned -1.5.0 Send over Mqtt the new status items and refactoring -1.4.1 Remove old Wirelesscode and Rename some Classes -1.4.0 Adding Debugmode for finetuning Lora-Trackers -1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value -1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile -1.1.0 Update Scral addresses + + 2.0.0 The total rewrite + 1.8.4 Fixing a bug related to threaded working with data + 1.8.3 Update to changed ConnectorDataMqtt and remove Scral from code, because its an own project now, that uses the mqtt-backend + 1.8.2 Bugfix, create also an event for sending normal loradata when update panic + 1.8.1 Add Hostname to MQTT, so you can see from witch device the data is recieved + 1.8.0 Add field that indicates when the last gps position was recieved, change all times to UTC + 1.7.3 Parsing new Status format and Panic Package + 1.7.2 Update to local librarys + 1.7.1 Fixing binary data transmission & fixing Scral Plugin + 1.7.0 Adding IC800A Lora-Reciever + 1.6.2 Adding a test for LoraBinary + 1.6.1 Fixing parsing bug with linebreaks in Lora + 1.6.0 Implement Height in LoraBot + 1.5.1 Dependencies in debian Packet cleaned + 1.5.0 Send over Mqtt the new status items and refactoring + 1.4.1 Remove old Wirelesscode and Rename some Classes + 1.4.0 Adding Debugmode for finetuning Lora-Trackers + 1.3.0 Scral now get its config from configfile, lora now want to get battery as [0-9].[0-9]{2} value + 1.2.0 Run Module Events in threads so that one Module can not block others, TXTOut now appends to the logfile + 1.1.0 Update Scral addresses + Fraunhofer.Fit.IoT.Bots.LoraBot.Program LoraBot.Bots.IoT.Fit.Fraunhofer @@ -48,8 +50,8 @@ - - + + @@ -57,7 +59,7 @@ - + diff --git a/Lora-Bot/Models/BinaryPacket.cs b/Lora-Bot/Models/BinaryPacket.cs index 5dfec2a..1e69ee2 100644 --- a/Lora-Bot/Models/BinaryPacket.cs +++ b/Lora-Bot/Models/BinaryPacket.cs @@ -6,23 +6,7 @@ namespace Fraunhofer.Fit.IoT.Bots.LoraBot.Models { public class BinaryPacket : Packet { - public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, RecievedData recieveddata) { - this.TransferData = new LocationUpdateEvent(typ) { - Name = name, - BatteryLevel = battery, - Gps = new GpsUpdateEvent() { - Latitude = lat, - Longitude = lon, - Hdop = hdop, - Height = height, - Fix = lat != 0 || lon != 0 - } - }; - this.Type = typ; - this.SetLoraData(recieveddata, this.TransferData); - } - - public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Single hdop, Single height, Single battery, UInt16 counter, Boolean has_time, Boolean has_date, Boolean has_fix, Byte sat, Boolean correct_if, String hash, RecievedData recieveddata) { + public BinaryPacket(String name, LoraParser.Typ typ, Single lat, Single lon, Double hdop, Double height, Double battery, UInt16 counter, Boolean has_time, Boolean has_date, Boolean has_fix, Byte sat, Boolean correct_if, String hash, RecievedData recieveddata) { this.TransferData = new LocationUpdateEvent(typ) { Name = name, BatteryLevel = battery, diff --git a/Lora-Bot/Parser/LoraParser.cs b/Lora-Bot/Parser/LoraParser.cs index ee45d46..8849f6f 100644 --- a/Lora-Bot/Parser/LoraParser.cs +++ b/Lora-Bot/Parser/LoraParser.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Security.Cryptography; using System.Text; @@ -70,18 +70,6 @@ public void ReceivedPacket(Object sender, RecievedData data) { } else { Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "|" + BitConverter.ToString(decoded).Replace("-", " ") + "| CRC:" + data.Crc); } - } else if (data.Data.Length == 21 && data.Data[0] == 'b' || data.Data[0] == 'p') { - //###### Binary Packet, starts with "b" or Panic Packet, starts with "p" ######### - BinaryPacket p = this.ParseBinaryPacket(data.Data, data); - if(p.Type == Typ.Data) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Data [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.DataUpdates(sender, p.TransferData); - } else if(p.Type == Typ.Panic) { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Panic [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| RSSI:" + data.Rssi + " SNR:" + data.Snr); - this.PanicUpdates(sender, p.TransferData); - } else { - Console.WriteLine("Fraunhofer.Fit.Iot.Lora.LoraController.ReceivePacket: Binary-Packet not Match! [" + data.Data.Length + "]|" + BitConverter.ToString(data.Data).Replace("-", " ") + "| CRC:" + data.Crc); - } } else if(data.Data.Length > 3 && data.Data[0] == 'd' && data.Data[1] == 'e' && data.Data[2] == 'b') { //###### Debug Packet, three lines ############# DebugPacket p = this.ParseDebugPacket(data.Data, data); @@ -126,7 +114,7 @@ private DebugPacket ParseDebugPacket(Byte[] data, RecievedData recieveddata) { String ipaddress = infos[1]; String wifissid = infos[2]; Boolean wifiactive = infos[3] == "t"; - _ = Double.TryParse(infos[4], out Double batteryLevel); + _ = Double.TryParse(infos[4], NumberStyles.Any, CultureInfo.InvariantCulture, out Double batteryLevel); _ = Int32.TryParse(infos[5], out Int32 freqOffset); Status status = Status.Unknown; if(Int32.TryParse(infos[6], out Int32 deviceStatus)) { @@ -147,38 +135,21 @@ private DebugPacket ParseDebugPacket(Byte[] data, RecievedData recieveddata) { } private BinaryPacket ParseBinaryPacket(Byte[] data, RecievedData recieveddata) { - if(data.Length == 21) { - Typ typ = Typ.Unknown; - if(data[0] == 'b') { - typ = Typ.Data; - } else if(data[0] == 'p') { - typ = Typ.Panic; - } - String name = data[2] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[1] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[1], data[2] }).Trim(); - Single lat = BitConverter.ToSingle(data, 3); - Single lon = BitConverter.ToSingle(data, 7); - Single hdop = (Single)data[11] / 10; - Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; - Single battery = ((Single)data[20] + 230) / 100; - return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, recieveddata); - } else if(data.Length == 18) { - UInt16 counter = BitConverter.ToUInt16(data, 0); - String name = data[3] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[2] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[3] }).Trim(); - Single lat = BitConverter.ToSingle(data, 4); - Single lon = BitConverter.ToSingle(data, 8); - Single height = (Single)BitConverter.ToUInt16(data, 12) / 10; - Single battery = ((Single)data[14] + 230) / 100; - Single hdop = (Single)data[15] / 10; - Typ typ = (data[16] & 0x80) != 0 ? Typ.Panic : Typ.Data; - Boolean has_time = (data[16] & 0x40) != 0 ? true : false; - Boolean has_date = (data[16] & 0x20) != 0 ? true : false; - Boolean has_fix = (data[16] & 0x10) != 0 ? true : false; - Byte sat = (Byte)(data[16] & 0x0F); - Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[2] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; - String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); - return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, counter, has_time, has_date, has_fix, sat, correct_if, hash, recieveddata); - } - return null; + UInt16 counter = BitConverter.ToUInt16(data, 0); + String name = data[3] == 0 ? Encoding.ASCII.GetString(new Byte[] { data[2] }).Trim() : Encoding.ASCII.GetString(new Byte[] { data[2], data[3] }).Trim(); + Single lat = BitConverter.ToSingle(data, 4); + Single lon = BitConverter.ToSingle(data, 8); + Double height = Math.Round((Single)BitConverter.ToUInt16(data, 12) / 10, 1); + Double battery = Math.Round(((Single)data[14] + 230) / 100, 2); + Double hdop = Math.Round((Single)data[15] / 10, 1); + Typ typ = (data[16] & 0x80) != 0 ? Typ.Panic : Typ.Data; + Boolean has_time = (data[16] & 0x40) != 0 ? true : false; + Boolean has_date = (data[16] & 0x20) != 0 ? true : false; + Boolean has_fix = (data[16] & 0x10) != 0 ? true : false; + Byte sat = (Byte)(data[16] & 0x0F); + Boolean correct_if = recieveddata is Ic880aRecievedObj ? data[2] % 8 == ((Ic880aRecievedObj)recieveddata).Interface : true; + String hash = BitConverter.ToString(this.SHA256Calc(data)).Replace("-", ""); + return new BinaryPacket(name, typ, lat, lon, hdop, height, battery, counter, has_time, has_date, has_fix, sat, correct_if, hash, recieveddata); } private Byte[] DecodeData(Byte[] encoded) { From f0570d24cee34b0dabc3604c67ce24b0cb270f96 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Thu, 23 Jan 2020 14:14:54 +0100 Subject: [PATCH 28/29] [2.0.0] The total rewrite --- Lora-Bot/Lora-Bot.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lora-Bot/Lora-Bot.csproj b/Lora-Bot/Lora-Bot.csproj index 845c931..e67f16d 100644 --- a/Lora-Bot/Lora-Bot.csproj +++ b/Lora-Bot/Lora-Bot.csproj @@ -1,4 +1,4 @@ - + Exe @@ -9,7 +9,7 @@ Fraunhofer FIT BlubbFish 2.0.0 - Copyright © Fraunhofer FIT, BlubbFish 2018 - 08.07.2019 + Copyright © Fraunhofer FIT, BlubbFish 2018 - 23.01.2020 LICENSE de-DE https://github.com/MONICA-Project/lora-bot From a51369feeaa72dad92f13e09ec81c07fd97237d6 Mon Sep 17 00:00:00 2001 From: Philip Schell Date: Thu, 23 Jan 2020 14:31:27 +0100 Subject: [PATCH 29/29] [2.0.0] The total rewrite --- .github/workflows/dotnetcore.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/dotnetcore.yml b/.github/workflows/dotnetcore.yml index b0e5923..0e53d4b 100644 --- a/.github/workflows/dotnetcore.yml +++ b/.github/workflows/dotnetcore.yml @@ -13,9 +13,9 @@ jobs: ref: refs/heads/master submodules: true - - name: Checkout last versions - run: git -C Lora checkout --progress --force dotnetcore - working-directory: ../lora-project +# - name: Checkout last versions +# run: git -C Lora checkout --progress --force dotnetcore +# working-directory: ../lora-project - name: Checkout last versions run: git -C Lora-Bot checkout --progress --force ${{ github.sha }}