diff --git a/ADIS_Csharp/ADIS_Csharp.sln b/ADIS_Csharp/ADIS_Csharp.sln index f203fb4..a644936 100644 --- a/ADIS_Csharp/ADIS_Csharp.sln +++ b/ADIS_Csharp/ADIS_Csharp.sln @@ -15,7 +15,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sync-Ueb04-NestedMonitor", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sync-Ueb05-LostSignals", "Sync-Ueb05-LostSignals\Sync-Ueb05-LostSignals.csproj", "{8605252D-7232-4E7A-B1E0-BF273947F3CB}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MqttTest", "MqttTest\MqttTest.csproj", "{EB76DC93-79D0-4837-8A49-D825CDE4C6A3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MqttTest", "MqttTest\MqttTest.csproj", "{EB76DC93-79D0-4837-8A49-D825CDE4C6A3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RobotLib", "RobotLib\RobotLib.csproj", "{915E2889-F10D-4D02-8313-308F642EC64F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -51,6 +53,10 @@ Global {EB76DC93-79D0-4837-8A49-D825CDE4C6A3}.Debug|Any CPU.Build.0 = Debug|Any CPU {EB76DC93-79D0-4837-8A49-D825CDE4C6A3}.Release|Any CPU.ActiveCfg = Release|Any CPU {EB76DC93-79D0-4837-8A49-D825CDE4C6A3}.Release|Any CPU.Build.0 = Release|Any CPU + {915E2889-F10D-4D02-8313-308F642EC64F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {915E2889-F10D-4D02-8313-308F642EC64F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {915E2889-F10D-4D02-8313-308F642EC64F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {915E2889-F10D-4D02-8313-308F642EC64F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/ADIS_Csharp/RobotLib/BatteryEventArgs.cs b/ADIS_Csharp/RobotLib/BatteryEventArgs.cs new file mode 100644 index 0000000..fb31787 --- /dev/null +++ b/ADIS_Csharp/RobotLib/BatteryEventArgs.cs @@ -0,0 +1,14 @@ +using System; + +namespace RobotLib +{ + public class BatteryEventArgs : EventArgs + { + public float Voltage { get; } + + public BatteryEventArgs(float voltage) + { + Voltage = voltage; + } + } +} diff --git a/ADIS_Csharp/RobotLib/ClassDiagram1.cd b/ADIS_Csharp/RobotLib/ClassDiagram1.cd new file mode 100644 index 0000000..456eaa1 --- /dev/null +++ b/ADIS_Csharp/RobotLib/ClassDiagram1.cd @@ -0,0 +1,35 @@ + + + + + + AAQAAAAAAAAAAAAAAAAAAIAAAAEAAAAAQAAAAAAAAAg= + Robot.cs + + + + + + + + + IAQAAAAAAAAAAAFAAAAACIgAAAAAAAAAAAAAAAAEAAI= + Com.cs + + + + + + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAA= + MessageEventArgs.cs + + + + + + AAAAAAAAAABAAAAAACAgCAgAAAEAAQAAAAAAAAAAAAA= + DevBase.cs + + + + \ No newline at end of file diff --git a/ADIS_Csharp/RobotLib/Com.cs b/ADIS_Csharp/RobotLib/Com.cs new file mode 100644 index 0000000..389d0d9 --- /dev/null +++ b/ADIS_Csharp/RobotLib/Com.cs @@ -0,0 +1,87 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace RobotLib +{ + public class Com + { + private static readonly NLog.Logger log = NLog.LogManager.GetCurrentClassLogger(); + private UdpClient udpClient; + private Thread thread; + + public event EventHandler MessageReveived; + + public Com() + { + } + + public Com(string host, int port) + { + Connect(host, port); + } + + public bool IsConnected { get; private set; } + + + public void Connect(string host, int port) + { + if (!IsConnected) + { + udpClient = new UdpClient(); + udpClient.Connect(host, port); + IsConnected = true; + + thread = new Thread(Run); + thread.IsBackground = true; + thread.Start(); + } + } + + public void Disconnect() + { + IsConnected = false; + if (thread != null) + { + thread.Interrupt(); + thread.Join(); + } + } + + public void Run() + { + while(IsConnected) + { + try + { + IPEndPoint remote = new IPEndPoint(IPAddress.Any, 0); + byte[] dataReceived = udpClient.Receive(ref remote); + string msg = Encoding.ASCII.GetString(dataReceived); + log.Trace($"Msg received from {remote}: {msg}"); + MessageReveived?.Invoke(this, new MessageEventArgs(msg)); + } + catch (ThreadInterruptedException) + { + return; + } + catch (Exception ex) + { + log.Fatal(ex, "Exception in Receiver-Thread\r\n" + ex); + } + } + } + + public void SendMsg(string msg) + { + byte[] data = Encoding.ASCII.GetBytes(msg); + udpClient.Send(data, data.Length); + log.Trace($"Msg sent to {udpClient.Client.RemoteEndPoint}: {msg}"); + } + + } +} diff --git a/ADIS_Csharp/RobotLib/DevBase.cs b/ADIS_Csharp/RobotLib/DevBase.cs new file mode 100644 index 0000000..a1ed02b --- /dev/null +++ b/ADIS_Csharp/RobotLib/DevBase.cs @@ -0,0 +1,51 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RobotLib +{ + public abstract class DevBase + { + protected NLog.Logger log { get; private set; } + + public DevBase(Com com) : this(com, string.Empty) { } + public DevBase(Com com, string keyword) + { + log = NLog.LogManager.GetLogger(GetType().ToString()); + + Keyword = keyword; + Com = com; + com.MessageReveived += MessageReveived; + } + + protected string Keyword { get; } + protected Com Com { get; } + + protected virtual void MessageReveived(object sender, MessageEventArgs e) + { + if (e.Message.StartsWith(Keyword)) + { + ParseMessage(e.Message); + } + } + + protected void SendMessage(string message) + { + if (Com.IsConnected) + { + log.Trace("Esp32> " + message); + Com.SendMsg(message); + } + else + { + log.Warn("Not connected! Could not send message: " + message); + } + } + protected virtual void ParseMessage(string message) { } + + public virtual void Refresh() { } + + } +} diff --git a/ADIS_Csharp/RobotLib/DevBattery.cs b/ADIS_Csharp/RobotLib/DevBattery.cs new file mode 100644 index 0000000..d1a7d0b --- /dev/null +++ b/ADIS_Csharp/RobotLib/DevBattery.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RobotLib +{ + public class DevBattery : DevBase + { + private float voltage; + + public event EventHandler BatteryChanged; + + public float Voltage + { + get { return voltage; } + private set + { + // value changed? + if(voltage != value) + { + // set new voltage and raise event + voltage = value; + BatteryChanged?.Invoke(this, new BatteryEventArgs(voltage)); + } + } + } + + public DevBattery(Com com) : base(com, "battery") { } + + public override void Refresh() + { + SendMessage("get battery status!"); + } + + protected override void ParseMessage(string message) + { + // example message = "Battery: 1.25 V" + var keyValue = message.Trim().Split(':'); + string key = keyValue[0].Trim(); + string value = keyValue[1].Trim(); + + switch (key) + { + case "battery": + value = value.Trim(' ', 'V'); + this.Voltage = float.Parse(value); + break; + + default: + log.Warn($"Unkown element {key}: {value} in message {message}"); + break; + } + + + } + } +} diff --git a/ADIS_Csharp/RobotLib/DevBuzzer.cs b/ADIS_Csharp/RobotLib/DevBuzzer.cs new file mode 100644 index 0000000..dbdb94a --- /dev/null +++ b/ADIS_Csharp/RobotLib/DevBuzzer.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RobotLib +{ + public class DevBuzzer : DevBase + { + public DevBuzzer(Com com) : base(com) { } + + public void Beep(int freq, int timeMs) + { + SendMessage($"robo sendcmd buzzer buzz {freq} {timeMs}!"); + } + } +} diff --git a/ADIS_Csharp/RobotLib/MessageEventArgs.cs b/ADIS_Csharp/RobotLib/MessageEventArgs.cs new file mode 100644 index 0000000..1582e20 --- /dev/null +++ b/ADIS_Csharp/RobotLib/MessageEventArgs.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace RobotLib +{ + public class MessageEventArgs : EventArgs + { + public MessageEventArgs(string msg) + { + Message = msg; + } + + + public string Message { get; } + } +} diff --git a/ADIS_Csharp/RobotLib/Robot.cs b/ADIS_Csharp/RobotLib/Robot.cs new file mode 100644 index 0000000..de6e71f --- /dev/null +++ b/ADIS_Csharp/RobotLib/Robot.cs @@ -0,0 +1,46 @@ +using System.Threading; + +namespace RobotLib +{ + public class Robot + { + + public static Robot Instance { get; } = new Robot(); + + + private Robot() + { + Com = new Com(); + Buzzer = new DevBuzzer(Com); + Battery = new DevBattery(Com); + + Timer timer = new Timer(TimerCallback); + timer.Change(2000, 10000); + } + + public Com Com { get; } + + public DevBuzzer Buzzer { get; } + public DevBattery Battery { get; } + + + public void Connect(string host, int port) + { + Com.Connect(host, port); + } + + public void Disconnect() + { + Com.Disconnect(); + } + + private void TimerCallback(object state) + { + if (Com.IsConnected) + { + Battery.Refresh(); + } + } + + } +} \ No newline at end of file diff --git a/ADIS_Csharp/RobotLib/RobotLib.csproj b/ADIS_Csharp/RobotLib/RobotLib.csproj new file mode 100644 index 0000000..9a8e66f --- /dev/null +++ b/ADIS_Csharp/RobotLib/RobotLib.csproj @@ -0,0 +1,11 @@ + + + + net6.0 + + + + + + +