diff --git a/.gitignore b/.gitignore
index bb1bfcb..e2c0f04 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,79 @@
################################################################################
/.svn
+/.vs
+/CorrelationsAttacker
+/flight hands
+/Utils/Utils/obj
+/Utils/Utils/bin/Debug
+/Utils/Utils/bin/Release/Utils.pdb
+/TT-Crawler
+/TestUsb
+/Testconsole
+/testapp
+/tconv
+/SWP
+/svnsync
+/svgb
+/Spielfeld
+/SmallptGPU-v1.6
+/Rollmorad
+/Rock_C
+/RailWorks_Joystick_API
+/PowerSwitcher
+/Plot
+/PicoSopeReader
+/OpenCLNet
+/OpenCLImageFilter
+/OpenCLFilter
+/OpenCL
+/netmonitor
+/mwPS
+/miranda
+/Matomat
+/MateBeweis
+/MailServer
+/LFSInsim
+/Joystik-Test
+/helloworld
+/gspylogin
+/GPSViewer
+/GPGPU
+/GoproControl
+/Gcc-Proxy
+/ebbits/.vs/ebbits/v15
+/ebbits/AdvancedServo-simple/obj/Debug
+/Mqtt-Dashboard/.vs/Dashboard/v15
+/Mqtt-Dashboard/Mqtt-Dashboard/obj
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Debug
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/ca.pem
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/cert.key
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/cert.pem
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Dashboard.exe.config
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Dashboard.pdb
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/M2Mqtt.Net.pdb
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.pdb
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.WindowsForms.pdb
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.WindowsForms.xml
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.xml
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/sensor.ini
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/settings.ini
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/tracings.ini
+/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils.pdb
+/Mqtt-Dashboard/packages
+/Mqtt-SWB-Dashboard/.vs
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Debug
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/ELE
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/SWB
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Mqtt-SWB-Dashboard.exe.config
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Mqtt-SWB-Dashboard.pdb
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.xml
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.Wpf.xml
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.Wpf.pdb
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.pdb
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Utils.pdb
+/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/obj
+/Mqtt-SWB-Dashboard/packages
+/TimeKeeper/Arduino/Zeit/Zeit-V2/Debug
+/TimeKeeper/Arduino/Zeit/Zeit-V2/__vm
+/TimeKeeper/lib/System.Data.SQLite.xml
diff --git a/Kinect/Demo1/Demo1.sln b/Kinect/Demo1/Demo1.sln
new file mode 100644
index 0000000..5ea3b88
--- /dev/null
+++ b/Kinect/Demo1/Demo1.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo1", "Demo1\Demo1.csproj", "{1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}.Debug|x86.ActiveCfg = Debug|x86
+ {1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}.Debug|x86.Build.0 = Debug|x86
+ {1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}.Release|x86.ActiveCfg = Release|x86
+ {1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo1/Demo1/App.xaml b/Kinect/Demo1/Demo1/App.xaml
new file mode 100644
index 0000000..dcbb72a
--- /dev/null
+++ b/Kinect/Demo1/Demo1/App.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/Kinect/Demo1/Demo1/App.xaml.cs b/Kinect/Demo1/Demo1/App.xaml.cs
new file mode 100644
index 0000000..42a2e84
--- /dev/null
+++ b/Kinect/Demo1/Demo1/App.xaml.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace Demo1
+{
+ ///
+ /// Interaktionslogik für "App.xaml"
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Kinect/Demo1/Demo1/Demo1.csproj b/Kinect/Demo1/Demo1/Demo1.csproj
new file mode 100644
index 0000000..d7fd1d9
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Demo1.csproj
@@ -0,0 +1,110 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {1D0066B4-E5EE-4F76-97E4-0372F1EFAE1E}
+ WinExe
+ Properties
+ Demo1
+ Demo1
+ v4.0
+ Client
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+ C:\Program Files\Microsoft SDKs\Kinect\v1.7\Assemblies\Microsoft.Kinect.dll
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo1/Demo1/DepthFrameConverter.cs b/Kinect/Demo1/Demo1/DepthFrameConverter.cs
new file mode 100644
index 0000000..fd0a4ea
--- /dev/null
+++ b/Kinect/Demo1/Demo1/DepthFrameConverter.cs
@@ -0,0 +1,137 @@
+using Microsoft.Kinect;
+using System.Drawing;
+
+namespace KinectWorkshop
+{
+ /*public class DepthFrameConverter
+ {
+ const int RED_IDX = 2;
+ const int GREEN_IDX = 1;
+ const int BLUE_IDX = 0;
+ byte[] depthFrame32 = new byte[320 * 240 * 4];
+
+ // Converts a 16-bit grayscale depth frame which includes player indexes into a 32-bit frame
+ // that displays different players in different colors
+ public byte[] ConvertDepthFrameWithUser(DepthImagePixel[] depthFrame, int width, int height)
+ {
+ Color c = Color.Empty;
+ byte[] ret = new byte[width * height * 4];
+ for (int x = 1; x < width; x++)
+ {
+ for (int y = 0; y < height; y++)
+ {
+ int i = ((y * width) + x) * 4;
+ short depth = (depthFrame[x + y * width]).Depth;
+ c = Color.Empty;
+ if(depth > 0 && depth <= 4000)
+ {
+ int depthdist = (int)((depth / 4090f) * 255f);
+ c = System.Drawing.Color.FromArgb((int)(depthdist / 2f), depthdist, (int)(depthdist * 0.7f));
+ }
+ ret[i] = c.B;
+ ret[i] = c.G;
+ ret[i] = c.R;
+ ret[i] = 255;
+ }
+
+ }
+
+ /* for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
+ {
+ int player = depthFrame16[i16] & 0x07;
+ //if ((y - 1) * 320 + x * 4 == i16)
+ //{
+ // player = 8;
+ //}
+ int realDepth = (depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
+ // transform 13-bit depth information into an 8-bit intensity appropriate
+ // for display (we disregard information in most significant bit)
+ byte intensity = (byte)(255 - (255 * realDepth / 0x0fff));
+
+ depthFrame32[i32 + RED_IDX] = 0;
+ depthFrame32[i32 + GREEN_IDX] = 0;
+ depthFrame32[i32 + BLUE_IDX] = 0;
+
+ // choose different display colors based on player
+ switch (player)
+ {
+ case 0:
+ depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 2);
+ break;
+ case 1:
+ depthFrame32[i32 + RED_IDX] = intensity;
+ break;
+ case 2:
+ depthFrame32[i32 + GREEN_IDX] = intensity;
+ break;
+ case 3:
+ depthFrame32[i32 + RED_IDX] = (byte)(intensity / 4);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
+ break;
+ case 4:
+ depthFrame32[i32 + RED_IDX] = (byte)(intensity);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(intensity);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(intensity / 4);
+ break;
+ case 5:
+ depthFrame32[i32 + RED_IDX] = (byte)(intensity);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 4);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
+ break;
+ case 6:
+ depthFrame32[i32 + RED_IDX] = (byte)(intensity / 2);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(intensity / 2);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(intensity);
+ break;
+ case 7:
+ depthFrame32[i32 + RED_IDX] = (byte)(255 - intensity);
+ depthFrame32[i32 + GREEN_IDX] = (byte)(255 - intensity);
+ depthFrame32[i32 + BLUE_IDX] = (byte)(255 - intensity);
+ break;
+ case 8:
+ depthFrame32[i32 + RED_IDX] = 255;
+ depthFrame32[i32 + GREEN_IDX] = 0;
+ depthFrame32[i32 + BLUE_IDX] = 0;
+ break;
+ }
+ }
+ return depthFrame32;*
+ return ret;
+ }
+
+ internal byte[] ConvertDepthFrame(byte[] depthFrame16)
+ {
+ for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
+ {
+ int realDepth = (depthFrame16[i16+1] << 8)|(depthFrame16[i16]);
+ //byte r = (byte)(realDepth >> 8);
+ //byte b = (byte)realDepth;
+ byte intensity = (byte)(255 - (255 * realDepth / 0x0fff));
+ depthFrame32[i32 + RED_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+ depthFrame32[i32 + GREEN_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+ depthFrame32[i32 + BLUE_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+
+ }
+ return depthFrame32;
+ }
+
+ internal byte[] ConvertDepthFrameHiddenPlayer(byte[] depthFrame16)
+ {
+ for (int i16 = 0, i32 = 0; i16 < depthFrame16.Length && i32 < depthFrame32.Length; i16 += 2, i32 += 4)
+ {
+ int realDepth = (depthFrame16[i16 + 1] << 5) | (depthFrame16[i16] >> 3);
+ //byte r = (byte)(realDepth >> 8);
+ //byte b = (byte)realDepth;
+ byte intensity = (byte)(255 - (255 * realDepth / 0x0fff));
+ depthFrame32[i32 + RED_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+ depthFrame32[i32 + GREEN_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+ depthFrame32[i32 + BLUE_IDX] = (byte)((intensity * -1) + 255);// (byte)(intensity / 2);
+
+ }
+ return depthFrame32;
+ }
+ }*/
+}
diff --git a/Kinect/Demo1/Demo1/MainWindow.xaml b/Kinect/Demo1/Demo1/MainWindow.xaml
new file mode 100644
index 0000000..ef57fc8
--- /dev/null
+++ b/Kinect/Demo1/Demo1/MainWindow.xaml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
diff --git a/Kinect/Demo1/Demo1/MainWindow.xaml.cs b/Kinect/Demo1/Demo1/MainWindow.xaml.cs
new file mode 100644
index 0000000..6f88874
--- /dev/null
+++ b/Kinect/Demo1/Demo1/MainWindow.xaml.cs
@@ -0,0 +1,257 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Microsoft.Kinect;
+
+namespace Demo1
+{
+ ///
+ /// Interaktionslogik für MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ private KinectWorkshop.DepthFrameConverter cv = new KinectWorkshop.DepthFrameConverter();
+ private KinectSensor r;
+ //private DepthImagePixel[] depthPixels;
+ //private byte[] colorPixels;
+ //private DepthImageFormat DepthFormat = DepthImageFormat.Resolution320x240Fps30;
+ //private ColorImageFormat ColorFormat = ColorImageFormat.RgbResolution640x480Fps30;
+ //private ColorImagePoint[] colorCoordinates;
+ //private bool init = false;
+
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (KinectSensor.KinectSensors.Count == 0)
+ {
+ MessageBox.Show("Keine Kinect");
+ return;
+ }
+ try
+ {
+ r = KinectSensor.KinectSensors[0];
+ r.Start();
+ //r.Initialize(RuntimeOptions.UseSkeletalTracking | RuntimeOptions.UseDepthAndPlayerIndex);
+
+ //r.VideoFrameReady += new EventHandler(r_VideoFrameReady);
+ //r.VideoStream.Open(ImageStreamType.Video, 2, ImageResolution.Resolution640x480, ImageType.Color);
+ //r.DepthFrameReady += r_DepthFrameReady;
+ //r.DepthStream.Enable();
+ //r.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.DepthAndPlayerIndex);
+ //r.SkeletonFrameReady += r_SkeletonFrameReady;
+ r.SkeletonStream.Enable(new TransformSmoothParameters() { Smoothing = 0.1f });
+ //r.SkeletonEngine.TransformSmooth = true;
+ //r.SkeletonFrameReady += new EventHandler(r_SkeletonFrameReady);
+ //_cam = r.NuiCamera;
+ //r.AllFramesReady += R_AllFramesReady;
+ r.SkeletonFrameReady += this.r_SkeletonFrameReady;
+ }
+ catch (Exception ex)
+ {
+ MessageBox.Show(ex.ToString());
+ }
+ }
+
+ /*private void R_AllFramesReady(object sender, AllFramesReadyEventArgs e)
+ {
+ if(r == null)
+ {
+ return;
+ }
+ bool depthReceived = false;
+ bool colorReceived = false;
+
+ using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
+ {
+ if (null != depthFrame)
+ {
+ // Copy the pixel data from the image to a temporary array
+ depthFrame.CopyDepthImagePixelDataTo(this.depthPixels);
+
+ depthReceived = true;
+ if(!init) {
+ this.colorCoordinates = new ColorImagePoint[r.DepthStream.FramePixelDataLength];
+ init = true;
+ }
+ }
+ }
+
+ using (ColorImageFrame colorFrame = e.OpenColorImageFrame())
+ {
+ if (null != colorFrame)
+ {
+ // Copy the pixel data from the image to a temporary array
+ colorFrame.CopyPixelDataTo(this.colorPixels);
+
+ colorReceived = true;
+ }
+ }
+
+ if (true == depthReceived)
+ {
+ r.CoordinateMapper.MapDepthFrameToColorFrame(
+ DepthFormat,
+ this.depthPixels,
+ ColorFormat,
+ this.colorCoordinates);
+
+ // ...
+
+ int depthIndex = x + (y * this.depthWidth);
+ DepthImagePixel depthPixel = this.depthPixels[depthIndex];
+
+ // scale color coordinates to depth resolution
+ int X = colorImagePoint.X / this.colorToDepthDivisor;
+ int Y = colorImagePoint.Y / this.colorToDepthDivisor;
+
+ // depthPixel is the depth for the (X,Y) pixel in the color frame
+ }
+
+ }*/
+
+ void r_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
+ {
+ SkeletonFrame skf = e.OpenSkeletonFrame();
+ if(skf == null)
+ {
+ return;
+ }
+ Skeleton[] sks = new Skeleton[skf.SkeletonArrayLength];
+ skf.CopySkeletonDataTo(sks);
+ this.MainCanvas.Children.Clear();
+ foreach (Skeleton sk in sks)
+ {
+ if (sk.TrackingState == SkeletonTrackingState.Tracked)
+ {
+ this.drawPlayer(sk);
+
+ }
+ }
+ }
+
+ private void drawPlayer(Skeleton sk)
+ {
+ this.SetPoints(sk);
+ this.SetLines(sk);
+ }
+
+ private void SetLines(Skeleton sk)
+ {
+ JointType[,] id = {
+ { JointType.Head, JointType.ShoulderCenter },
+ { JointType.ShoulderCenter, JointType.ShoulderLeft },
+ { JointType.ShoulderCenter, JointType.ShoulderRight },
+ { JointType.ShoulderLeft, JointType.ElbowLeft },
+ { JointType.ShoulderRight, JointType.ElbowRight },
+ { JointType.ElbowLeft, JointType.WristLeft },
+ { JointType.ElbowRight, JointType.WristRight },
+ { JointType.WristLeft, JointType.HandLeft },
+ { JointType.WristRight, JointType.HandRight },
+ { JointType.ShoulderCenter, JointType.Spine },
+ { JointType.Spine, JointType.HipCenter },
+ { JointType.HipCenter, JointType.HipLeft },
+ { JointType.HipCenter, JointType.HipRight },
+ { JointType.HipLeft, JointType.KneeLeft },
+ { JointType.HipRight, JointType.KneeRight },
+ { JointType.KneeLeft, JointType.AnkleLeft },
+ { JointType.KneeRight, JointType.AnkleRight },
+ { JointType.AnkleLeft, JointType.FootLeft },
+ { JointType.AnkleRight, JointType.FootRight }
+ };
+ for (int i = 0; i < id.Length / 2; i++)
+ {
+ Joint r1 = sk.Joints[id[i, 0]].ScaleTo(640, 480);
+ Joint r2 = sk.Joints[id[i, 1]].ScaleTo(640, 480);
+
+ /**** */
+ Line l = new Line();
+ l.Stroke = Brushes.Blue;
+ l.StrokeThickness = 5.0;
+ l.Y1 = r1.Position.Y;
+ l.X1 = r1.Position.X;
+ l.Y2 = r2.Position.Y;
+ l.X2 = r2.Position.X;
+ /**** */
+
+ this.MainCanvas.Children.Add(l);
+ }
+ }
+
+ private void SetPoints(Skeleton sk)
+ {
+ foreach (Joint joint in sk.Joints)
+ {
+ Joint p = joint.ScaleTo(640, 480);
+ Ellipse e = new Ellipse();
+ e.Fill = Brushes.Red;
+ e.Stroke = Brushes.Black;
+ e.Height = 10;
+ e.Width = 10;
+ Canvas.SetLeft(e, p.Position.X - e.Width / 2);
+ Canvas.SetTop(e, p.Position.Y - e.Height / 2);
+ this.MainCanvas.Children.Add(e);
+ }
+ }
+
+ /*void r_DepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
+ {
+ //PlanarImage img = e.ImageFrame.Image;
+ DepthImageFrame img = e.OpenDepthImageFrame();
+ if(img == null)
+ {
+ return;
+ }
+ DepthImagePixel[] bs = new DepthImagePixel[img.PixelDataLength];
+ img.CopyDepthImagePixelDataTo(bs);
+ byte[] bh = cv.ConvertDepthFrameWithUser(bs, img.Width, img.Height);
+ imgDepth.Source = BitmapSource.Create(img.Width, img.Height, 96, 96, PixelFormats.Bgr32, null, bh, img.Width * 4);
+ //bh = cv.ConvertDepthFrameHiddenPlayer(img.Bits);
+ //byte[] bh = cv.ConvertDepthFrame(img.Bits);
+ //imgDepthPlayer.Source = BitmapSource.Create(img.Width, img.Height,
+ // 96, 96, PixelFormats.Bgr32, null,
+ // bh, img.Width * 4);
+ }*/
+
+ private void Window_KeyUp(object sender, KeyEventArgs e)
+ {
+ try
+ {
+ if (e.Key == Key.Up)
+ {
+ int k = r.ElevationAngle;
+ k++;
+ r.ElevationAngle = k;
+ }
+ if (e.Key == Key.Down)
+ r.ElevationAngle -= 1;
+ }
+ catch (ArgumentOutOfRangeException outOfRangeException)
+ {
+ MessageBox.Show(outOfRangeException.Message);
+ }
+ catch (Exception) { }
+ }
+
+ /*void r_VideoFrameReady(object sender, ImageFrameReadyEventArgs e)
+ {
+ PlanarImage img = e.ImageFrame.Image;
+ imgRgb.Source = BitmapSource.Create(img.Width, img.Height,
+ 96, 96, PixelFormats.Bgr32, null,
+ img.Bits, img.Width * img.BytesPerPixel);
+ }*/
+ }
+}
diff --git a/Kinect/Demo1/Demo1/Properties/AssemblyInfo.cs b/Kinect/Demo1/Demo1/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b85ddc9
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo1")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo1")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
+//ImCodeVerwendeteKultur in der .csproj-Datei
+//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
+//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
+//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
+//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
+ //(wird verwendet, wenn eine Ressource auf der Seite
+ // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
+ ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
+ //(wird verwendet, wenn eine Ressource auf der Seite, in der Anwendung oder einem
+ // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
+)]
+
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo1/Demo1/Properties/Resources.Designer.cs b/Kinect/Demo1/Demo1/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..527f4a9
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.239
+//
+// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
+// der Code neu generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo1.Properties
+{
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
+ // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo1.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo1/Demo1/Properties/Resources.resx b/Kinect/Demo1/Demo1/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Kinect/Demo1/Demo1/Properties/Settings.Designer.cs b/Kinect/Demo1/Demo1/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..8bffaa1
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.239
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo1.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo1/Demo1/Properties/Settings.settings b/Kinect/Demo1/Demo1/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Kinect/Demo1/Demo1/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo1/Demo1/SkeletalCommonExtensions.cs b/Kinect/Demo1/Demo1/SkeletalCommonExtensions.cs
new file mode 100644
index 0000000..a13c436
--- /dev/null
+++ b/Kinect/Demo1/Demo1/SkeletalCommonExtensions.cs
@@ -0,0 +1,41 @@
+using Microsoft.Kinect;
+using System.Windows;
+
+namespace Demo1
+{
+ internal static class SkeletalCommonExtensions
+ {
+ public static Joint ScaleTo(this Joint joint, int width, int height, float skeletonMaxX, float skeletonMaxY)
+ {
+ SkeletonPoint pos = new SkeletonPoint()
+ {
+ X = Scale(width, skeletonMaxX, joint.Position.X),
+ Y = Scale(height, skeletonMaxY, -joint.Position.Y),
+ Z = joint.Position.Z
+ };
+
+ Joint j = new Joint()
+ {
+ TrackingState = joint.TrackingState,
+ Position = pos
+ };
+
+ return j;
+ }
+
+ public static Joint ScaleTo(this Joint joint, int width, int height)
+ {
+ return ScaleTo(joint, width, height, 1.0f, 1.0f);
+ }
+
+ private static float Scale(int maxPixel, float maxSkeleton, float position)
+ {
+ float value = ((((maxPixel / maxSkeleton) / 2) * position) + (maxPixel / 2));
+ if (value > maxPixel)
+ return maxPixel;
+ if (value < 0)
+ return 0;
+ return value;
+ }
+ }
+}
diff --git a/Kinect/Demo2/Demo2.sln b/Kinect/Demo2/Demo2.sln
new file mode 100644
index 0000000..e38c107
--- /dev/null
+++ b/Kinect/Demo2/Demo2.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo2", "Demo2\Demo2.csproj", "{12018BA3-A02D-488C-83F6-1799D344C1C3}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {12018BA3-A02D-488C-83F6-1799D344C1C3}.Debug|x86.ActiveCfg = Debug|x86
+ {12018BA3-A02D-488C-83F6-1799D344C1C3}.Debug|x86.Build.0 = Debug|x86
+ {12018BA3-A02D-488C-83F6-1799D344C1C3}.Release|x86.ActiveCfg = Release|x86
+ {12018BA3-A02D-488C-83F6-1799D344C1C3}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo2/Demo2/Demo2.csproj b/Kinect/Demo2/Demo2/Demo2.csproj
new file mode 100644
index 0000000..1f2ac6b
--- /dev/null
+++ b/Kinect/Demo2/Demo2/Demo2.csproj
@@ -0,0 +1,58 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {12018BA3-A02D-488C-83F6-1799D344C1C3}
+ Exe
+ Properties
+ Demo2
+ Demo2
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo2/Demo2/Program.cs b/Kinect/Demo2/Demo2/Program.cs
new file mode 100644
index 0000000..1b3dbd7
--- /dev/null
+++ b/Kinect/Demo2/Demo2/Program.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Research.Kinect.Nui;
+
+namespace Demo2
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ if (Runtime.Kinects.Count == 0)
+ {
+ Console.WriteLine("KEine Kinect");
+ return;
+ }
+ Runtime r = Runtime.Kinects[0];
+ r.Initialize(RuntimeOptions.UseSkeletalTracking);
+ r.SkeletonFrameReady += new EventHandler(r_SkeletonFrameReady);
+ r.SkeletonEngine.TransformSmooth = true;
+
+ Console.ReadLine();
+ r.Uninitialize();
+ }
+
+ static void r_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
+ {
+ foreach (SkeletonData sk in e.SkeletonFrame.Skeletons)
+ {
+ if (sk.TrackingState == SkeletonTrackingState.Tracked)
+ {
+ Joint l = sk.Joints[JointID.HandLeft];
+ Joint r = sk.Joints[JointID.HandRight];
+ Console.WriteLine("Left Hand: X:{0}, Y:{1}, Z:{2}", l.Position.X, l.Position.Y, l.Position.Z);
+ Console.WriteLine("Right Hand: X:{0}, Y:{1}, Z:{2}", r.Position.X, r.Position.Y, r.Position.Z);
+ }
+ }
+ Console.WriteLine();
+ }
+ }
+}
diff --git a/Kinect/Demo2/Demo2/Properties/AssemblyInfo.cs b/Kinect/Demo2/Demo2/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0a95656
--- /dev/null
+++ b/Kinect/Demo2/Demo2/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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 mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo2")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo2")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("c0c8b6f9-5275-4f3b-a622-0a78d2a3a3dd")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo3/Demo3.sln b/Kinect/Demo3/Demo3.sln
new file mode 100644
index 0000000..a061036
--- /dev/null
+++ b/Kinect/Demo3/Demo3.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo3", "Demo3\Demo3.csproj", "{33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}.Debug|x86.ActiveCfg = Debug|x86
+ {33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}.Debug|x86.Build.0 = Debug|x86
+ {33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}.Release|x86.ActiveCfg = Release|x86
+ {33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo3/Demo3/Demo3.csproj b/Kinect/Demo3/Demo3/Demo3.csproj
new file mode 100644
index 0000000..d0604f1
--- /dev/null
+++ b/Kinect/Demo3/Demo3/Demo3.csproj
@@ -0,0 +1,63 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {33D30437-2141-4BEE-B4DE-FBF5B01F7A8C}
+ Exe
+ Properties
+ Demo3
+ Demo3
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+ False
+ C:\Program Files\Microsoft Speech Platform SDK\Assembly\Microsoft.Speech.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo3/Demo3/Program.cs b/Kinect/Demo3/Demo3/Program.cs
new file mode 100644
index 0000000..4832dfe
--- /dev/null
+++ b/Kinect/Demo3/Demo3/Program.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Demo3
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ KinectWorkshop.SpeechToText stt = new KinectWorkshop.SpeechToText();
+ stt.TextRecognized += new EventHandler(stt_TextRecognized);
+ stt.Start();
+ Console.ReadLine();
+ stt.Stop();
+ }
+
+ static void stt_TextRecognized(object sender, KinectWorkshop.SpeechToText.TextRecognizedArgs e)
+ {
+ Console.WriteLine(e.Verb);
+ switch (e.Verb)
+ {
+ case KinectWorkshop.SpeechToText.Verbs.None:
+ break;
+ case KinectWorkshop.SpeechToText.Verbs.PreviousSlide:
+ break;
+ case KinectWorkshop.SpeechToText.Verbs.NextSlide:
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo3/Demo3/Properties/AssemblyInfo.cs b/Kinect/Demo3/Demo3/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..20cc130
--- /dev/null
+++ b/Kinect/Demo3/Demo3/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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 mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo3")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo3")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("1fd608c9-3dd2-4d4b-b7a0-c368ff56a377")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo3/Demo3/SpeechToText.cs b/Kinect/Demo3/Demo3/SpeechToText.cs
new file mode 100644
index 0000000..5dc8780
--- /dev/null
+++ b/Kinect/Demo3/Demo3/SpeechToText.cs
@@ -0,0 +1,136 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+using System.Threading;
+using Microsoft.Research.Kinect.Audio;
+using Microsoft.Speech.AudioFormat;
+using Microsoft.Speech.Recognition;
+
+namespace KinectWorkshop
+{
+ public class SpeechToText
+ {
+ public enum Verbs
+ {
+ None = 0,
+ PreviousSlide,
+ NextSlide
+ };
+
+ Dictionary SinglePhrases = new Dictionary()
+ {
+ {"previous slide", Verbs.PreviousSlide},
+ {"next slide", Verbs.NextSlide}
+ };
+
+ public class TextRecognizedArgs : EventArgs
+ {
+ public Verbs Verb { get; set; }
+ public string Phrase { get; set; }
+ public string Matched {get; set; }
+ }
+
+ public event EventHandler TextRecognized;
+
+ private KinectAudioSource kinectSource;
+ private SpeechRecognitionEngine sre;
+ private const string RecognizerId = "SR_MS_en-US_Kinect_10.0";
+
+ public SpeechToText()
+ {
+ RecognizerInfo ri = SpeechRecognitionEngine.InstalledRecognizers().Where(r => r.Id == RecognizerId).FirstOrDefault();
+ if (ri == null)
+ return;
+
+ sre = new SpeechRecognitionEngine(ri.Id);
+ var singlePhrases = new Choices();
+ foreach (var phrase in SinglePhrases)
+ singlePhrases.Add(phrase.Key);
+
+ var g = new Grammar(new GrammarBuilder(singlePhrases));
+ sre.LoadGrammar(g);
+ sre.SpeechRecognized += sre_SpeechRecognized;
+ sre.SpeechRecognitionRejected += new EventHandler(sre_SpeechRecognitionRejected);
+ }
+
+ private void StartSST()
+ {
+ kinectSource = new KinectAudioSource();
+ kinectSource.SystemMode = SystemMode.OptibeamArrayOnly;
+ kinectSource.FeatureMode = true;
+ kinectSource.AutomaticGainControl = false;
+ kinectSource.MicArrayMode = MicArrayMode.MicArrayAdaptiveBeam;
+ var kinectStream = kinectSource.Start();
+ sre.SetInputToAudioStream(kinectStream, new SpeechAudioFormatInfo(
+ EncodingFormat.Pcm, 16000, 16, 1,
+ 32000, 2, null));
+ sre.RecognizeAsync(RecognizeMode.Multiple);
+
+ //const double alpha = 0.35;
+ //double angle = 0.0;
+ //while (true)
+ //{
+ // if (kinectSource.SoundSourcePositionConfidence > 0.5)
+ // {
+ // double a = alpha*kinectSource.SoundSourcePositionConfidence;
+ // angle = (1 - a) * angle + a * kinectSource.SoundSourcePosition;
+ // Console.WriteLine(angle + ":" + kinectSource.MicArrayBeamAngle);
+ // }
+ // System.Threading.Thread.Sleep(50);
+ //}
+ }
+
+ public void Start()
+ {
+ var t = new Thread(StartSST);
+ t.Start();
+ }
+
+ public void Stop()
+ {
+ if (sre != null)
+ {
+ sre.RecognizeAsyncCancel();
+ sre.RecognizeAsyncStop();
+ kinectSource.Dispose();
+ }
+ }
+
+ void sre_SpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
+ {
+ var said = new TextRecognizedArgs();
+ said.Verb = Verbs.None;
+ said.Matched = "?";
+ TextRecognized(new object(), said);
+ Console.WriteLine("\nSpeech Rejected");
+ }
+
+ void sre_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
+ {
+ if (TextRecognized == null)
+ return;
+
+ var said = new TextRecognizedArgs();
+ said.Verb = Verbs.None;
+ said.Phrase = e.Result.Text;
+
+ bool found = false;
+ foreach (var phrase in SinglePhrases)
+ {
+ if (e.Result.Text.Contains(phrase.Key))
+ {
+ said.Verb = phrase.Value;
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ return;
+
+ TextRecognized(new object(), said);
+ }
+ }
+}
\ No newline at end of file
diff --git a/Kinect/Demo4/Demo4.sln b/Kinect/Demo4/Demo4.sln
new file mode 100644
index 0000000..fc5a88e
--- /dev/null
+++ b/Kinect/Demo4/Demo4.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo4", "Demo4\Demo4.csproj", "{FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}.Debug|x86.ActiveCfg = Debug|x86
+ {FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}.Debug|x86.Build.0 = Debug|x86
+ {FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}.Release|x86.ActiveCfg = Release|x86
+ {FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo4/Demo4/Demo4.csproj b/Kinect/Demo4/Demo4/Demo4.csproj
new file mode 100644
index 0000000..8bbd77e
--- /dev/null
+++ b/Kinect/Demo4/Demo4/Demo4.csproj
@@ -0,0 +1,60 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {FBF0FD4F-54D6-4077-AE63-F98C1FD10FBC}
+ Exe
+ Properties
+ Demo4
+ Demo4
+ v4.0
+ Client
+ 512
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo4/Demo4/KeySender.cs b/Kinect/Demo4/Demo4/KeySender.cs
new file mode 100644
index 0000000..90fa244
--- /dev/null
+++ b/Kinect/Demo4/Demo4/KeySender.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace KinectWorkshop
+{
+ public enum VirtualKey : ushort
+ {
+ SHIFT = 0x10,
+ CONTROL = 0x11,
+ MENU = 0x12,
+ ESCAPE = 0x1B,
+ BACK = 0x08,
+ TAB = 0x09,
+ RETURN = 0x0D,
+ PRIOR = 0x21,
+ NEXT = 0x22,
+ END = 0x23,
+ HOME = 0x24,
+ LEFT = 0x25,
+ UP = 0x26,
+ RIGHT = 0x27,
+ DOWN = 0x28,
+ SELECT = 0x29,
+ PRINT = 0x2A,
+ EXECUTE = 0x2B,
+ SNAPSHOT = 0x2C,
+ INSERT = 0x2D,
+ DELETE = 0x2E,
+ HELP = 0x2F,
+ NUMPAD0 = 0x60,
+ NUMPAD1 = 0x61,
+ NUMPAD2 = 0x62,
+ NUMPAD3 = 0x63,
+ NUMPAD4 = 0x64,
+ NUMPAD5 = 0x65,
+ NUMPAD6 = 0x66,
+ NUMPAD7 = 0x67,
+ NUMPAD8 = 0x68,
+ NUMPAD9 = 0x69,
+ MULTIPLY = 0x6A,
+ ADD = 0x6B,
+ SEPARATOR = 0x6C,
+ SUBTRACT = 0x6D,
+ DECIMAL = 0x6E,
+ DIVIDE = 0x6F,
+ F1 = 0x70,
+ F2 = 0x71,
+ F3 = 0x72,
+ F4 = 0x73,
+ F5 = 0x74,
+ F6 = 0x75,
+ F7 = 0x76,
+ F8 = 0x77,
+ F9 = 0x78,
+ F10 = 0x79,
+ F11 = 0x7A,
+ F12 = 0x7B,
+ OEM_1 = 0xBA, // ',:' for US
+ OEM_PLUS = 0xBB, // '+' any country
+ OEM_COMMA = 0xBC, // ',' any country
+ OEM_MINUS = 0xBD, // '-' any country
+ OEM_PERIOD = 0xBE, // '.' any country
+ OEM_2 = 0xBF, // '/?' for US
+ OEM_3 = 0xC0, // '`~' for US
+ MEDIA_NEXT_TRACK = 0xB0,
+ MEDIA_PREV_TRACK = 0xB1,
+ MEDIA_STOP = 0xB2,
+ MEDIA_PLAY_PAUSE = 0xB3,
+ LWIN =0x5B,
+ RWIN =0x5C
+ }
+
+ class KeySender
+ {
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
+
+ public struct KEYBDINPUT
+ {
+ public ushort wVk;
+ public ushort wScan;
+ public uint dwFlags;
+ public long time;
+ public uint dwExtraInfo;
+ }
+
+ [StructLayout(LayoutKind.Explicit, Size = 28)]
+ public struct INPUT
+ {
+ [FieldOffset(0)]
+ public uint type;
+ [FieldOffset(4)]
+ public KEYBDINPUT ki;
+ }
+
+ public enum Win32Consts : int
+ {
+ INPUT_MOUSE = 0,
+ INPUT_KEYBOARD = 1,
+ INPUT_HARDWARE = 2,
+ }
+
+ public static void Send(VirtualKey key)
+ {
+ INPUT structInput = new INPUT();
+ structInput.type = (uint)Win32Consts.INPUT_KEYBOARD;
+ structInput.ki.wVk = (ushort)key;
+ SendInput(1, ref structInput, Marshal.SizeOf(structInput));
+ }
+ }
+}
diff --git a/Kinect/Demo4/Demo4/Program.cs b/Kinect/Demo4/Demo4/Program.cs
new file mode 100644
index 0000000..3e447c1
--- /dev/null
+++ b/Kinect/Demo4/Demo4/Program.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using Microsoft.Research.Kinect.Nui;
+
+namespace Demo4
+{
+ class Program
+ {
+ private static DateTime lastTimeHit;
+ static void Main(string[] args)
+ {
+ if (Runtime.Kinects.Count == 0)
+ {
+ Console.WriteLine("Keine Kinect");
+ return;
+ }
+ Runtime r = Runtime.Kinects[0];
+ r.Initialize(RuntimeOptions.UseSkeletalTracking);
+ r.SkeletonEngine.TransformSmooth = true;
+
+ r.SkeletonFrameReady += new EventHandler(r_SkeletonFrameReady);
+
+ Console.ReadLine();
+ r.Uninitialize();
+ }
+
+ static void r_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
+ {
+ if ((DateTime.Now - lastTimeHit).Seconds < 5)
+ {
+ return;
+ }
+ foreach (SkeletonData s in e.SkeletonFrame.Skeletons)
+ {
+ if (s.TrackingState == SkeletonTrackingState.Tracked)
+ {
+ Joint rh = s.Joints[JointID.HandRight];
+ Joint h = s.Joints[JointID.Head];
+
+ if (rh.Position.Y > h.Position.Y)
+ {
+ lastTimeHit = DateTime.Now;
+ Console.WriteLine("Hand über kopf");
+ IntPtr hwnd = KinectWorkshop.WindowFinder.StartingWith("Unbenannt");
+ KinectWorkshop.WindowFinder.SetFocusOn(hwnd);
+ KinectWorkshop.KeySender.Send(KinectWorkshop.VirtualKey.NEXT);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo4/Demo4/Properties/AssemblyInfo.cs b/Kinect/Demo4/Demo4/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..54bfbd3
--- /dev/null
+++ b/Kinect/Demo4/Demo4/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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 mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo4")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo4")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("aa436451-b12f-49c9-aa04-728a278274ee")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo4/Demo4/WindowFinder.cs b/Kinect/Demo4/Demo4/WindowFinder.cs
new file mode 100644
index 0000000..2b73d1f
--- /dev/null
+++ b/Kinect/Demo4/Demo4/WindowFinder.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace KinectWorkshop
+{
+ class WindowFinder
+ {
+ [DllImport("user32.dll", SetLastError = true)]
+ static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
+
+ [DllImport("user32.Dll")]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, [MarshalAsAttribute(UnmanagedType.Struct)] ref SearchData data);
+ private delegate bool EnumWindowsProc(IntPtr hWnd, ref SearchData data);
+
+ [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
+ public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
+
+ [DllImport("user32.dll")]
+ static extern IntPtr SetFocus(IntPtr hWnd);
+
+ struct SearchData
+ {
+ public string TitlePrefix;
+ public IntPtr hWnd;
+ }
+
+ static bool EnumProc(IntPtr hWnd, ref SearchData data)
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ GetWindowText(hWnd, sb, sb.Capacity);
+ if (sb.ToString().StartsWith(data.TitlePrefix))
+ {
+ data.hWnd = hWnd;
+ return false;
+ }
+ return true;
+ }
+
+ public static IntPtr StartingWith(string prefix)
+ {
+ SearchData sd = new SearchData { TitlePrefix = prefix };
+ EnumWindows(new EnumWindowsProc(EnumProc), ref sd);
+ return sd.hWnd;
+ }
+
+ public static void SetFocusOn(IntPtr hwnd)
+ {
+ SetFocus(hwnd);
+ }
+ }
+}
diff --git a/Kinect/Demo5/Demo5.sln b/Kinect/Demo5/Demo5.sln
new file mode 100644
index 0000000..075f0ab
--- /dev/null
+++ b/Kinect/Demo5/Demo5.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo5", "Demo5\Demo5.csproj", "{CF078AB1-B658-48F7-89C1-45610E317B3D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {CF078AB1-B658-48F7-89C1-45610E317B3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CF078AB1-B658-48F7-89C1-45610E317B3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CF078AB1-B658-48F7-89C1-45610E317B3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CF078AB1-B658-48F7-89C1-45610E317B3D}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo5/Demo5/Class1.cs b/Kinect/Demo5/Demo5/Class1.cs
new file mode 100644
index 0000000..e88091f
--- /dev/null
+++ b/Kinect/Demo5/Demo5/Class1.cs
@@ -0,0 +1,11 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace Demo5
+{
+ public class Class1
+ {
+ }
+}
diff --git a/Kinect/Demo5/Demo5/Demo5.csproj b/Kinect/Demo5/Demo5/Demo5.csproj
new file mode 100644
index 0000000..7b9b769
--- /dev/null
+++ b/Kinect/Demo5/Demo5/Demo5.csproj
@@ -0,0 +1,81 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {CF078AB1-B658-48F7-89C1-45610E317B3D}
+ Library
+ Properties
+ Demo5
+ Demo5
+ v4.0
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ true
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+
+
+ KinectDemo5.snk
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ UserControl
+
+
+ KinectControl.cs
+
+
+
+
+ KinectControl.cs
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo5/Demo5/KinectControl.Designer.cs b/Kinect/Demo5/Demo5/KinectControl.Designer.cs
new file mode 100644
index 0000000..e8b735c
--- /dev/null
+++ b/Kinect/Demo5/Demo5/KinectControl.Designer.cs
@@ -0,0 +1,72 @@
+namespace Demo5
+{
+ partial class KinectControl
+ {
+ ///
+ /// Erforderliche Designervariable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Verwendete Ressourcen bereinigen.
+ ///
+ /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Komponenten-Designer generierter Code
+
+ ///
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ ///
+ private void InitializeComponent()
+ {
+ this.lbHandLeft = new System.Windows.Forms.Label();
+ this.lbHandRight = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // lbHandLeft
+ //
+ this.lbHandLeft.AutoSize = true;
+ this.lbHandLeft.Location = new System.Drawing.Point(3, 15);
+ this.lbHandLeft.Name = "lbHandLeft";
+ this.lbHandLeft.Size = new System.Drawing.Size(59, 13);
+ this.lbHandLeft.TabIndex = 0;
+ this.lbHandLeft.Text = "lbHandLeft";
+ //
+ // lbHandRight
+ //
+ this.lbHandRight.AutoSize = true;
+ this.lbHandRight.Location = new System.Drawing.Point(84, 15);
+ this.lbHandRight.Name = "lbHandRight";
+ this.lbHandRight.Size = new System.Drawing.Size(66, 13);
+ this.lbHandRight.TabIndex = 1;
+ this.lbHandRight.Text = "lbHandRight";
+ //
+ // KinectControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.lbHandRight);
+ this.Controls.Add(this.lbHandLeft);
+ this.Name = "KinectControl";
+ this.Size = new System.Drawing.Size(150, 46);
+ this.Load += new System.EventHandler(this.KinectControl_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label lbHandLeft;
+ private System.Windows.Forms.Label lbHandRight;
+ }
+}
diff --git a/Kinect/Demo5/Demo5/KinectControl.cs b/Kinect/Demo5/Demo5/KinectControl.cs
new file mode 100644
index 0000000..30ff5c3
--- /dev/null
+++ b/Kinect/Demo5/Demo5/KinectControl.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Data;
+using System.Linq;
+using System.Text;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using Microsoft.Win32;
+using System.Reflection;
+using Microsoft.Research.Kinect.Nui;
+
+
+namespace Demo5
+{
+ [ProgId("Demo5.KinectControl")]
+ [Guid("577410DD-1FC4-4B28-A0FE-9D0F78CEEDB5")]
+ [ClassInterface(ClassInterfaceType.AutoDual)]
+ [ComVisible(true)]
+ public partial class KinectControl : UserControl
+ {
+ private string text;
+ [ComRegisterFunction()]
+ public static void RegisterClass(string key)
+ {
+ StringBuilder sb = new StringBuilder(key);
+ sb.Replace(@"HKEY_CLASSES_ROOT\", "");
+
+ RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
+ RegistryKey ctrl = k.CreateSubKey("Control");
+ ctrl.Close();
+
+ RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
+ inprocServer32.SetValue("CodeBase", Assembly.GetExecutingAssembly().CodeBase);
+ inprocServer32.Close();
+
+ k.Close();
+ }
+
+ [ComUnregisterFunction()]
+ public static void UnregisterClass(string key)
+ {
+ StringBuilder sb = new StringBuilder(key);
+ sb.Replace(@"HKEY_CLASSES_ROOT\", "");
+
+ RegistryKey k = Registry.ClassesRoot.OpenSubKey(sb.ToString(), true);
+ k.DeleteSubKey("Control", false);
+ RegistryKey inprocServer32 = k.OpenSubKey("InprocServer32", true);
+ inprocServer32.DeleteSubKey("CodeBase", false);
+ inprocServer32.Close();
+ k.Close();
+ }
+
+
+
+ public KinectControl()
+ {
+ InitializeComponent();
+ }
+
+ private void KinectControl_Load(object sender, EventArgs e)
+ {
+ Runtime r = Runtime.Kinects[0];
+ r.Initialize(RuntimeOptions.UseSkeletalTracking);
+ r.SkeletonEngine.TransformSmooth = true;
+ r.SkeletonFrameReady += new EventHandler(r_SkeletonFrameReady);
+ }
+
+ void r_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
+ {
+ foreach (SkeletonData s in e.SkeletonFrame.Skeletons)
+ {
+ if (s.TrackingState == SkeletonTrackingState.Tracked)
+ {
+ Joint lh = s.Joints[JointID.HandLeft];
+ this.text = String.Format("X: {0}, Y: {1}", lh.Position.X, lh.Position.Y);
+ this.Invoke(new CallMe(SetText));
+ }
+ }
+ }
+
+ void SetText()
+ {
+ lbHandLeft.Text = this.text;
+ }
+
+ delegate void CallMe();
+ }
+}
diff --git a/Kinect/Demo5/Demo5/KinectControl.resx b/Kinect/Demo5/Demo5/KinectControl.resx
new file mode 100644
index 0000000..1af7de1
--- /dev/null
+++ b/Kinect/Demo5/Demo5/KinectControl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Kinect/Demo5/Demo5/KinectDemo5.snk b/Kinect/Demo5/Demo5/KinectDemo5.snk
new file mode 100644
index 0000000..eb5081d
Binary files /dev/null and b/Kinect/Demo5/Demo5/KinectDemo5.snk differ
diff --git a/Kinect/Demo5/Demo5/Properties/AssemblyInfo.cs b/Kinect/Demo5/Demo5/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..961bc36
--- /dev/null
+++ b/Kinect/Demo5/Demo5/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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 mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo5")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo5")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("75922dfb-1c32-4750-9af7-48d92b2c969d")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo5/Demo5/TextFile1.txt b/Kinect/Demo5/Demo5/TextFile1.txt
new file mode 100644
index 0000000..030ffae
--- /dev/null
+++ b/Kinect/Demo5/Demo5/TextFile1.txt
@@ -0,0 +1,2 @@
+regasm demo.dll
+regasm /u demo.dll
\ No newline at end of file
diff --git a/Kinect/Demo6/Demo6.sln b/Kinect/Demo6/Demo6.sln
new file mode 100644
index 0000000..bfa7e06
--- /dev/null
+++ b/Kinect/Demo6/Demo6.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 11.00
+# Visual Studio 2010
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo6", "Demo6\Demo6.csproj", "{9775B675-99C5-4DAD-8F6E-757002AE51D4}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {9775B675-99C5-4DAD-8F6E-757002AE51D4}.Debug|x86.ActiveCfg = Debug|x86
+ {9775B675-99C5-4DAD-8F6E-757002AE51D4}.Debug|x86.Build.0 = Debug|x86
+ {9775B675-99C5-4DAD-8F6E-757002AE51D4}.Release|x86.ActiveCfg = Release|x86
+ {9775B675-99C5-4DAD-8F6E-757002AE51D4}.Release|x86.Build.0 = Release|x86
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Kinect/Demo6/Demo6/App.xaml b/Kinect/Demo6/Demo6/App.xaml
new file mode 100644
index 0000000..f742932
--- /dev/null
+++ b/Kinect/Demo6/Demo6/App.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/Kinect/Demo6/Demo6/App.xaml.cs b/Kinect/Demo6/Demo6/App.xaml.cs
new file mode 100644
index 0000000..63a8aa8
--- /dev/null
+++ b/Kinect/Demo6/Demo6/App.xaml.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Windows;
+
+namespace Demo6
+{
+ ///
+ /// Interaktionslogik für "App.xaml"
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/Kinect/Demo6/Demo6/Demo6.csproj b/Kinect/Demo6/Demo6/Demo6.csproj
new file mode 100644
index 0000000..ef8b88e
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Demo6.csproj
@@ -0,0 +1,104 @@
+
+
+
+ Debug
+ x86
+ 8.0.30703
+ 2.0
+ {9775B675-99C5-4DAD-8F6E-757002AE51D4}
+ WinExe
+ Properties
+ Demo6
+ Demo6
+ v4.0
+ Client
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+
+
+ x86
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x86
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Kinect/Demo6/Demo6/MainWindow.xaml b/Kinect/Demo6/Demo6/MainWindow.xaml
new file mode 100644
index 0000000..e10986c
--- /dev/null
+++ b/Kinect/Demo6/Demo6/MainWindow.xaml
@@ -0,0 +1,8 @@
+
+
+
+
+
diff --git a/Kinect/Demo6/Demo6/MainWindow.xaml.cs b/Kinect/Demo6/Demo6/MainWindow.xaml.cs
new file mode 100644
index 0000000..3f2772b
--- /dev/null
+++ b/Kinect/Demo6/Demo6/MainWindow.xaml.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Microsoft.Research.Kinect.Nui;
+
+namespace Demo6
+{
+ ///
+ /// Interaktionslogik für MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+ InitializeComponent();
+ }
+
+ private void Window_Loaded(object sender, RoutedEventArgs e)
+ {
+ if (Runtime.Kinects.Count == 0)
+ {
+ MessageBox.Show("Keine Kinect");
+ return;
+ }
+ Runtime r = Runtime.Kinects[0];
+ r.Initialize(RuntimeOptions.UseDepth);
+ r.DepthStream.Open(ImageStreamType.Depth, 2, ImageResolution.Resolution320x240, ImageType.Depth);
+ r.DepthFrameReady += new EventHandler(r_DepthFrameReady);
+ }
+
+ void r_DepthFrameReady(object sender, ImageFrameReadyEventArgs e)
+ {
+ PlanarImage img = e.ImageFrame.Image;
+ //byte[] b = cv.ConvertDepthFrame(img.Bits);
+ imgDepth.Source = BitmapSource.Create(img.Width, img.Height,
+ 96, 96, PixelFormats.Bgr32, null,
+ b, img.Width * img.BytesPerPixel);
+ }
+ }
+}
diff --git a/Kinect/Demo6/Demo6/Properties/AssemblyInfo.cs b/Kinect/Demo6/Demo6/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..7884b85
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Demo6")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Demo6")]
+[assembly: AssemblyCopyright("Copyright © 2011")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
+//ImCodeVerwendeteKultur in der .csproj-Datei
+//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
+//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
+//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
+//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
+ //(wird verwendet, wenn eine Ressource auf der Seite
+ // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
+ ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
+ //(wird verwendet, wenn eine Ressource auf der Seite, in der Anwendung oder einem
+ // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
+)]
+
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Kinect/Demo6/Demo6/Properties/Resources.Designer.cs b/Kinect/Demo6/Demo6/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..8fb4bab
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.239
+//
+// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
+// der Code neu generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo6.Properties
+{
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
+ // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Demo6.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo6/Demo6/Properties/Resources.resx b/Kinect/Demo6/Demo6/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Kinect/Demo6/Demo6/Properties/Settings.Designer.cs b/Kinect/Demo6/Demo6/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..9f82a6f
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.239
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Demo6.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Kinect/Demo6/Demo6/Properties/Settings.settings b/Kinect/Demo6/Demo6/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Kinect/Demo6/Demo6/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Dashboard.sln b/Mqtt-Dashboard/Dashboard.sln
new file mode 100644
index 0000000..0789cb8
--- /dev/null
+++ b/Mqtt-Dashboard/Dashboard.sln
@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26403.7
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dashboard", "Mqtt-Dashboard\Dashboard.csproj", "{16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}.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
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/App.config b/Mqtt-Dashboard/Mqtt-Dashboard/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Connector/ADataBackend.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/ADataBackend.cs
new file mode 100644
index 0000000..33a0301
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/ADataBackend.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+
+namespace Dashboard.Connector {
+ public abstract class ADataBackend {
+
+ public abstract event MqttMessage MessageIncomming;
+ public abstract event MqttMessage MessageSending;
+ public delegate void MqttMessage(Object sender, MqttEventArgs e);
+
+ public static ADataBackend GetInstance(Dictionary dictionary) {
+ String object_sensor = "Dashboard.Connector." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower();
+ Type t = null;
+ try {
+ t = Type.GetType(object_sensor, true);
+ } catch (TypeLoadException) {
+ throw new ArgumentException("settings.ini: " + dictionary["type"] + " is not a Connector");
+ }
+ return (ADataBackend)t.GetConstructor(new Type[] { typeof(Dictionary) }).Invoke(new Object[] { dictionary });
+ }
+
+ public abstract void Send(String topic, String data);
+
+ public abstract void Dispose();
+ }
+ public class MqttEventArgs : EventArgs {
+ public MqttEventArgs() : base() { }
+ public MqttEventArgs(String message, String topic) {
+ this.Topic = topic;
+ this.Message = message;
+ this.Date = DateTime.Now;
+ }
+
+ public String Topic { get; private set; }
+ public String Message { get; private set; }
+ public DateTime Date { get; private set; }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mosquitto.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mosquitto.cs
new file mode 100644
index 0000000..cf88022
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mosquitto.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Dashboard.Connector {
+ class Mosquitto : ADataBackend, IDisposable {
+ private Process p;
+ private String message;
+
+ public override event MqttMessage MessageIncomming;
+ public override event MqttMessage MessageSending;
+
+ public Mosquitto(Dictionary mqtt_settings) {
+ this.settings = mqtt_settings;
+ //mosquitto_sub --cafile ca.pem --cert cert.pem --key cert.key -h swb.broker.flex4grid.eu -p 8883 -t "#" -v -d
+ this.message = "";
+ this.p = new Process();
+ this.p.StartInfo.FileName = "mosquitto_sub";
+ String args = "-h " + this.settings["server"]+" ";
+ if(this.settings.ContainsKey("port")) {
+ args += "-p "+ this.settings["port"]+" ";
+ }
+ if (this.settings.ContainsKey("cafile")) {
+ args += "--cafile " + this.settings["cafile"] + " ";
+ }
+ if (this.settings.ContainsKey("cert")) {
+ args += "--cert " + this.settings["cert"] + " ";
+ }
+ if (this.settings.ContainsKey("key")) {
+ args += "--key " + this.settings["key"] + " ";
+ }
+ this.p.StartInfo.Arguments = args+"-t \"#\" -v -d";
+ this.p.StartInfo.CreateNoWindow = true;
+ this.p.StartInfo.UseShellExecute = false;
+ this.p.StartInfo.RedirectStandardOutput = true;
+ this.p.StartInfo.RedirectStandardError = true;
+ this.p.OutputDataReceived += this.P_OutputDataReceived;
+ this.p.ErrorDataReceived += this.P_ErrorDataReceived;
+ this.p.Start();
+ this.p.BeginOutputReadLine();
+
+ }
+
+ public override void Send(String topic, String data) {
+ Process send = new Process();
+ send.StartInfo.FileName = "mosquitto_pub";
+ String args = "-h " + this.settings["server"] + " ";
+ if (this.settings.ContainsKey("port")) {
+ args += "-p " + this.settings["port"] + " ";
+ }
+ if (this.settings.ContainsKey("cafile")) {
+ args += "--cafile " + this.settings["cafile"] + " ";
+ }
+ if (this.settings.ContainsKey("cert")) {
+ args += "--cert " + this.settings["cert"] + " ";
+ }
+ if (this.settings.ContainsKey("key")) {
+ args += "--key " + this.settings["key"] + " ";
+ }
+ send.StartInfo.Arguments = args + "-m \""+data.Replace("\"","\\\"")+"\" -t \""+topic+"\" -d";
+ send.StartInfo.CreateNoWindow = true;
+ send.StartInfo.UseShellExecute = false;
+ send.StartInfo.RedirectStandardOutput = true;
+ send.StartInfo.RedirectStandardError = true;
+ send.Start();
+ send.WaitForExit();
+ MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
+ }
+
+ private void P_ErrorDataReceived(Object sender, DataReceivedEventArgs e) {
+ if (e.Data != null) {
+ throw new NotImplementedException(e.Data);
+ }
+ }
+
+ private void P_OutputDataReceived(Object sender, DataReceivedEventArgs e) {
+ if (e.Data != null) {
+ if (e.Data.StartsWith("Client mosqsub")) {
+ if (this.message != "" && this.message.IndexOf(" received PUBLISH ") > 0) {
+ MatchCollection matches = (new Regex("^Client mosqsub[\\|/].*received PUBLISH \\(.*,.*,.*,.*, '(.*)'.*\\)\\)\n[^ ]* (.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Matches(this.message);
+ String topic = matches[0].Groups[1].Value;
+ String message = matches[0].Groups[2].Value.Trim();
+ this.MessageIncomming?.Invoke(this, new MqttEventArgs(message, topic));
+ }
+ this.message = e.Data + "\n";
+ } else {
+ this.message += e.Data + "\n";
+ }
+ }
+ }
+
+ #region IDisposable Support
+ private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
+ private readonly Dictionary settings;
+
+ protected virtual void Dispose(Boolean disposing) {
+ if (!this.disposedValue) {
+ if (disposing) {
+ this.p.CancelOutputRead();
+ if (!this.p.HasExited) {
+ this.p.Kill();
+ }
+ this.p.Close();
+ }
+ this.p = null;
+ this.disposedValue = true;
+ }
+ }
+
+ ~Mosquitto() {
+ Dispose(false);
+ }
+
+ public override void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mqtt.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mqtt.cs
new file mode 100644
index 0000000..36d21a4
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Mqtt.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using BlubbFish.Utils;
+using uPLibrary.Networking.M2Mqtt;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace Dashboard.Connector {
+ class Mqtt : ADataBackend, IDisposable {
+ private MqttClient client;
+
+ public override event MqttMessage MessageIncomming;
+ public override event MqttMessage MessageSending;
+
+ public Mqtt(Dictionary settings) {
+ if(settings.ContainsKey("port")) {
+ this.client = new MqttClient(settings["server"], Int32.Parse(settings["port"]), false, null, null, MqttSslProtocols.None);
+ } else {
+ this.client = new MqttClient(settings["server"]);
+ }
+ Connect();
+ }
+
+ private void Connect() {
+ this.client.MqttMsgPublishReceived += this.Client_MqttMsgPublishReceived;
+ this.client.Connect(Guid.NewGuid().ToString());
+ this.client.Subscribe(new String[] { "#" }, new Byte[] { MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE });
+ }
+
+ private void Client_MqttMsgPublishReceived(Object sender, MqttMsgPublishEventArgs e) {
+ this.MessageIncomming?.Invoke(this, new MqttEventArgs(Encoding.UTF8.GetString(e.Message), e.Topic));
+ }
+
+ public override void Send(String topic, String data) {
+ this.client.Publish(topic, Encoding.UTF8.GetBytes(data));
+ this.MessageSending?.Invoke(this, new MqttEventArgs(data, topic));
+ }
+
+ #region IDisposable Support
+ private Boolean disposedValue = false;
+
+
+
+ protected virtual void Dispose(Boolean disposing) {
+ if(!this.disposedValue) {
+ if(disposing) {
+ this.client.MqttMsgPublishReceived -= this.Client_MqttMsgPublishReceived;
+ this.client.Unsubscribe(new String[] { "#" });
+ this.client.Disconnect();
+ }
+
+ this.client = null;
+
+ this.disposedValue = true;
+ }
+ }
+ ~Mqtt() {
+ Dispose(false);
+ }
+ public override void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Telegram.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Telegram.cs
new file mode 100644
index 0000000..4ec1ded
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Connector/Telegram.cs
@@ -0,0 +1,54 @@
+using BlubbFish.Utils;
+using System;
+using Telegram.Bot;
+using Telegram.Bot.Args;
+using Telegram.Bot.Exceptions;
+using Telegram.Bot.Types;
+
+namespace MqttToTelegram {
+ class Telegram {
+ private static Telegram instance;
+ private TelegramBotClient bot;
+ private ChatId chat;
+
+ public delegate void TelegramMessage(Object sender, Message e);
+
+ public event TelegramMessage MessageIncomming;
+ public event TelegramMessage MessageSending;
+
+ private Telegram() {
+ bot = new TelegramBotClient(InIReader.GetInstance("settings.ini").GetValue("general", "telegram-key"));
+ bot.OnMessage += Bot_OnMessage;
+ this.Connect();
+ }
+
+ private void Bot_OnMessage(Object sender, MessageEventArgs e) {
+ this.MessageIncomming?.Invoke(this, e.Message);
+ }
+
+ public static Telegram Instance {
+ get {
+ if(instance == null) {
+ instance = new Telegram();
+ }
+ return instance;
+ }
+ }
+
+ private void Connect() {
+ bot.StartReceiving();
+ this.chat = new ChatId(InIReader.GetInstance("settings.ini").GetValue("general", "chatid"));
+ }
+
+ public async void Send(String text) {
+ try {
+ Message x = await this.bot.SendTextMessageAsync(this.chat, text);
+ this.MessageSending?.Invoke(this, x);
+ } catch(ApiRequestException e) {
+ Console.ForegroundColor = ConsoleColor.Red;
+ Console.WriteLine(e.Message+" "+e.ErrorCode+" "+e.Parameters);
+ Console.ForegroundColor = ConsoleColor.White;
+ }
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj b/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj
new file mode 100644
index 0000000..6780600
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj
@@ -0,0 +1,149 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {16AC0F61-0B60-4A1D-A827-B3BFDBA9AAC7}
+ WinExe
+ Dashboard
+ Dashboard
+ v4.5.2
+ 512
+ true
+ publish\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ DEBUG
+ prompt
+ 4
+
+
+
+
+
+
+ ..\packages\LitJson.0.9.0\lib\LitJson.dll
+
+
+ ..\packages\M2Mqtt.4.3.0.0\lib\net45\M2Mqtt.Net.dll
+
+
+ ..\packages\OxyPlot.Core.1.0.0\lib\net45\OxyPlot.dll
+
+
+ ..\packages\OxyPlot.WindowsForms.1.0.0\lib\net45\OxyPlot.WindowsForms.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form
+
+
+ Form1.cs
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form1.cs
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+ Designer
+
+
+ True
+ Resources.resx
+ True
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+ True
+ Settings.settings
+ True
+
+
+
+
+
+
+
+
+
+
+ {fac8ce64-bf13-4ece-8097-aeb5dd060098}
+ Utils
+
+
+
+
+ False
+ Microsoft .NET Framework 4.5.2 %28x86 und x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj.user b/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj.user
new file mode 100644
index 0000000..67fe57a
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Dashboard.csproj.user
@@ -0,0 +1,19 @@
+
+
+
+ -debug
+
+
+ -debug
+
+
+
+
+
+
+
+
+ de-DE
+ false
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Form1.Designer.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.Designer.cs
new file mode 100644
index 0000000..65a1049
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.Designer.cs
@@ -0,0 +1,65 @@
+namespace Dashboard {
+ partial class Dashboard {
+ ///
+ /// Erforderliche Designervariable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Verwendete Ressourcen bereinigen.
+ ///
+ /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.
+ protected override void Dispose(bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Vom Windows Form-Designer generierter Code
+
+ ///
+ /// Erforderliche Methode für die Designerunterstützung.
+ /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
+ ///
+ private void InitializeComponent() {
+ this.statusStrip1 = new System.Windows.Forms.StatusStrip();
+ this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel();
+ this.SuspendLayout();
+ //
+ // statusStrip1
+ //
+ this.statusStrip1.Location = new System.Drawing.Point(0, 490);
+ this.statusStrip1.Name = "statusStrip1";
+ this.statusStrip1.Size = new System.Drawing.Size(1247, 22);
+ this.statusStrip1.TabIndex = 0;
+ this.statusStrip1.Text = "statusStrip1";
+ //
+ // flowLayoutPanel2
+ //
+ this.flowLayoutPanel2.Location = new System.Drawing.Point(12, 12);
+ this.flowLayoutPanel2.Name = "flowLayoutPanel2";
+ this.flowLayoutPanel2.Size = new System.Drawing.Size(1223, 475);
+ this.flowLayoutPanel2.TabIndex = 3;
+ //
+ // Dashboard
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1247, 512);
+ this.Controls.Add(this.flowLayoutPanel2);
+ this.Controls.Add(this.statusStrip1);
+ this.Name = "Dashboard";
+ this.Text = "Dashboard";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.StatusStrip statusStrip1;
+ private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2;
+ }
+}
+
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Form1.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.cs
new file mode 100644
index 0000000..a05edce
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.cs
@@ -0,0 +1,72 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using BlubbFish.Utils;
+using Dashboard.Connector;
+using Dashboard.Sensor;
+using Dashboard.Tracings;
+
+namespace Dashboard {
+ public partial class Dashboard : Form {
+ private Dictionary sensors = new Dictionary();
+ private ADataBackend mqtt;
+
+ public Dashboard(Boolean debug) {
+ InitializeComponent();
+ this.mqtt = ADataBackend.GetInstance(InIReader.GetInstance("settings.ini").GetSection("mqtt"));
+
+ this.GenerateSensors();
+ this.GenerateForms();
+
+ this.FormClosed += this.Dashboard_FormClosed;
+ this.SizeChanged += this.Dashboard_SizeChanged;
+
+ if (debug) {
+ this.mqtt.MessageIncomming += this.Instance_MessageIncomming;
+ this.mqtt.MessageSending += this.Instance_MessageSending;
+ }
+ }
+
+ private void Dashboard_SizeChanged(Object sender, EventArgs e) {
+ this.flowLayoutPanel2.Size = new System.Drawing.Size(this.Size.Width - 40, this.Size.Width - 76);
+ }
+
+ private void GenerateSensors() {
+ InIReader ini = InIReader.GetInstance("sensor.ini");
+ List sensorini = ini.GetSections(false);
+ foreach(String sensor in sensorini) {
+ this.sensors.Add(sensor.ToLower(), ASensor.GetInstance(this.mqtt, ini.GetSection(sensor), sensor));
+ }
+ }
+
+ private void GenerateForms() {
+ InIReader ini = InIReader.GetInstance("tracings.ini");
+ List tracingini = ini.GetSections();
+ foreach(String tracing in tracingini) {
+ this.flowLayoutPanel2.Controls.Add(ATracings.GetInstance(ini.GetValue(tracing, "type").ToLower(), this.sensors, ini.GetSection(tracing)).GetPanel());
+ }
+ }
+
+ private void Dashboard_FormClosed(Object sender, FormClosedEventArgs e) {
+ this.Dispose();
+ }
+ private new void Dispose() {
+ foreach (KeyValuePair item in this.sensors) {
+ item.Value.Dispose();
+ }
+ this.sensors.Clear();
+ this.mqtt.MessageIncomming -= this.Instance_MessageIncomming;
+ this.mqtt.MessageSending -= this.Instance_MessageSending;
+ this.mqtt.Dispose();
+ this.Dispose(true);
+ }
+
+ private void Instance_MessageIncomming(Object sender, MqttEventArgs e) {
+ Console.WriteLine("Received = " + e.Message + " on topic " + e.Topic+" at "+DateTime.Now.ToUniversalTime());
+ }
+
+ private void Instance_MessageSending(Object sender, MqttEventArgs e) {
+ Console.WriteLine("Sended = " + e.Message + " on topic " + e.Topic + " at " + DateTime.Now.ToUniversalTime());
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Form1.resx b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.resx
new file mode 100644
index 0000000..174ebc7
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Form1.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Program.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Program.cs
new file mode 100644
index 0000000..16afd1f
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Program.cs
@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using BlubbFish.Utils;
+
+namespace Dashboard {
+ static class Program {
+ ///
+ /// Der Haupteinstiegspunkt für die Anwendung.
+ ///
+ [STAThread]
+ static void Main(String[] args) {
+ CmdArgs.Instance.SetArguments(new Dictionary {
+ { "-debug", new CmdArgs.VaildArguments(CmdArgs.ArgLength.Single) }
+ }, args);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Boolean debug = false;
+ if(CmdArgs.Instance.HasArgumentType("-debug")) {
+ debug = true;
+ }
+ Application.Run(new Dashboard(debug));
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Properties/AssemblyInfo.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..ace93fe
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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("Mqtt-Dashboard")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Mqtt-Dashboard")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 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("16ac0f61-0b60-4a1d-a827-b3bfdba9aac7")]
+
+// 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.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.Designer.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..3c03f1c
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.Designer.cs
@@ -0,0 +1,63 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Dashboard.Properties {
+ using System;
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
+ // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Dashboard.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.resx b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.Designer.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..073a096
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.42000
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Dashboard.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.1.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.settings b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.settings
new file mode 100644
index 0000000..3964565
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/ASensor.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/ASensor.cs
new file mode 100644
index 0000000..ccbd6b7
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/ASensor.cs
@@ -0,0 +1,121 @@
+using Dashboard.Connector;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading;
+using System.Text.RegularExpressions;
+
+namespace Dashboard.Sensor {
+ public abstract class ASensor : IDisposable {
+ protected String topic;
+ protected Int32 pollcount;
+ private Dictionary settings;
+ protected ADataBackend backend;
+ private Thread updateThread;
+ private Boolean pollEnabled = false;
+
+ public ASensor(Dictionary settings, String name, ADataBackend backend) {
+ this.GetBool = true;
+ this.GetFloat = 0.0f;
+ this.GetInt = 0;
+ this.topic = (settings.Keys.Contains("topic")) ? settings["topic"] : "";
+ this.settings = settings;
+ this.Title = (settings.Keys.Contains("title")) ? settings["title"] : "";
+ this.Name = name;
+ this.backend = backend;
+ this.backend.MessageIncomming += this.IncommingMqttMessage;
+ if (settings.Keys.Contains("polling")) {
+ this.pollEnabled = true;
+ this.Polling = Int32.Parse(settings["polling"]);
+ this.pollcount = this.Polling;
+ this.updateThread = new Thread(this.SensorPolling);
+ this.updateThread.Start();
+ }
+ }
+
+ private void SensorPolling() {
+ while(this.pollEnabled) {
+ Thread.Sleep(1000);
+ this.Poll();
+ }
+ }
+
+ private void IncommingMqttMessage(Object sender, MqttEventArgs e) {
+ if(Regex.Match(e.Topic, this.topic).Success) {
+ if (this.UpdateValue(e)) {
+ this.Timestamp = DateTime.Now;
+ this.Update?.Invoke(this, e);
+ }
+ }
+ }
+
+ internal static ASensor GetInstance(ADataBackend backend, Dictionary dictionary, String name) {
+ String object_sensor = "Dashboard.Sensor." + Char.ToUpper(dictionary["type"][0]) + dictionary["type"].Substring(1).ToLower();
+ Type t = null;
+ try {
+ t = Type.GetType(object_sensor, true);
+ } catch(TypeLoadException) {
+ throw new ArgumentException("sensor.ini: " + dictionary["type"] + " is not a Sensor");
+ }
+ return (ASensor)t.GetConstructor(new Type[] { typeof(Dictionary), typeof(String), typeof(ADataBackend) }).Invoke(new Object[] { dictionary, name, backend });
+ }
+
+ protected virtual void Poll() {
+ if(this.pollcount++ >= this.Polling) {
+ this.pollcount = 1;
+ this.backend.Send(this.topic + "/status","");
+ }
+ }
+
+ internal virtual void SetBool(Boolean v) {
+ this.backend.Send(this.topic + "/set", v ? "on" : "off");
+ }
+
+ protected abstract Boolean UpdateValue(MqttEventArgs e);
+
+ public Single GetFloat { get; protected set; }
+ public Boolean GetBool { get; protected set; }
+ public Int32 GetInt { get; protected set; }
+ public Types Datatypes { get; protected set; }
+ public DateTime Timestamp { get; protected set; }
+ public Int32 Polling { get; private set; }
+ public String Title { get; protected set; }
+ public String Name { get; internal set; }
+
+ public enum Types {
+ Bool,
+ Int,
+ Float
+ }
+ public delegate void UpdatedValue(ASensor sender, EventArgs e);
+ public event UpdatedValue Update;
+
+ #region IDisposable Support
+ private Boolean disposedValue = false;
+
+
+ protected virtual void Dispose(Boolean disposing) {
+ if(!this.disposedValue) {
+ if(disposing) {
+ this.pollEnabled = false;
+ if (this.updateThread != null && this.updateThread.ThreadState == ThreadState.Running) {
+ this.updateThread.Abort();
+ while (this.updateThread.ThreadState != ThreadState.Aborted) { }
+ }
+ this.backend.MessageIncomming -= this.IncommingMqttMessage;
+ }
+ this.settings = null;
+ this.updateThread = null;
+ this.disposedValue = true;
+ }
+ }
+ ~ASensor() {
+ Dispose(false);
+ }
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4GridSwitch.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4GridSwitch.cs
new file mode 100644
index 0000000..20deb4d
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4GridSwitch.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using Dashboard.Connector;
+using LitJson;
+
+namespace Dashboard.Sensor {
+ class Flex4gridswitch : ASensor {
+ private String id;
+
+ public Flex4gridswitch(Dictionary settings, String name, ADataBackend backend) : base(settings, name, backend) {
+ this.Datatypes = Types.Bool;
+ this.id = settings["id"];
+ }
+
+ protected override Boolean UpdateValue(MqttEventArgs e) {
+ CultureInfo info = new CultureInfo("de-DE");
+ info.NumberFormat.NumberDecimalSeparator = ".";
+ CultureInfo.DefaultThreadCurrentCulture = info;
+ CultureInfo.DefaultThreadCurrentUICulture = info;
+ System.Threading.Thread.CurrentThread.CurrentCulture = info;
+ System.Threading.Thread.CurrentThread.CurrentUICulture = info;
+ try {
+ JsonData data = JsonMapper.ToObject(e.Message);
+ if (data.Keys.Contains("id") && data["id"].ToString() == this.id) {
+ this.GetBool = data["status"].ToString() == "active" ? true : false;
+ return true;
+ }
+ if(data.Keys.Contains(this.id)) {
+ this.GetBool = data[this.id].ToString() == "active" ? true : false;
+ return true;
+ }
+ } catch (Exception) {
+ }
+ return false;
+ }
+
+ protected override void Poll() {
+ if (this.pollcount++ >= this.Polling) {
+ this.pollcount = 1;
+ String hid = Regex.Match(this.topic, "/flex4grid/v1/households/([^/]*)/device/state").Groups[1].Value;
+ this.backend.Send("/flex4grid/v1/households/" + hid + "/devices/state/request", "{\"timestamp\": \"" + DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") + "\"}");
+ }
+ }
+
+ internal override void SetBool(Boolean v) {
+ String hid = Regex.Match(this.topic, "/flex4grid/v1/households/([^/]*)/device/state").Groups[1].Value;
+ this.backend.Send("/flex4grid/v1/households/" + hid + "/device/actuate", "{\"command\":\""+(v ? "ON" : "OFF") + "\",\"deviceId\":\""+ this.id + "\",\"timestamp\":\"" + DateTime.Now.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'ffffff'Z'") + "\"}");
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4gridPower.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4gridPower.cs
new file mode 100644
index 0000000..db95d9a
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Flex4gridPower.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Dashboard.Connector;
+using LitJson;
+
+namespace Dashboard.Sensor {
+ class Flex4gridpower : ASensor {
+ private String id;
+
+ public Flex4gridpower(Dictionary settings, String name, ADataBackend backend) : base(settings, name, backend) {
+ this.Datatypes = Types.Float;
+ this.id = settings["id"];
+ }
+
+ protected override Boolean UpdateValue(MqttEventArgs e) {
+ CultureInfo info = new CultureInfo("de-DE");
+ info.NumberFormat.NumberDecimalSeparator = ".";
+ CultureInfo.DefaultThreadCurrentCulture = info;
+ CultureInfo.DefaultThreadCurrentUICulture = info;
+ System.Threading.Thread.CurrentThread.CurrentCulture = info;
+ System.Threading.Thread.CurrentThread.CurrentUICulture = info;
+ try {
+ JsonData data = JsonMapper.ToObject(e.Message);
+ if(data["id"].ToString() == this.id) {
+ this.GetFloat = Single.Parse(data["power"].ToString());
+ return true;
+ }
+ } catch (Exception) {
+ }
+ return false;
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Luminanz.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Luminanz.cs
new file mode 100644
index 0000000..1e5eb9f
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Luminanz.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace Dashboard.Sensor {
+ class Luminanz : ASensor {
+ public Luminanz(Dictionary settings) : base(settings) {
+ this.GetBool = true;
+ this.GetFloat = 0.0f;
+ this.GetInt = 0;
+ this.Datatypes = Types.Int;
+ }
+
+ protected override void UpdateValue(MqttMsgPublishEventArgs e) {
+ this.GetInt = Int32.Parse(Encoding.UTF8.GetString(e.Message), new CultureInfo("en-US"));
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Pir.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Pir.cs
new file mode 100644
index 0000000..79f8d8f
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Pir.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace Dashboard.Sensor {
+ class Pir : ASensor {
+ public Pir(Dictionary settings) : base(settings) {
+ this.Datatypes = Types.Bool;
+ }
+
+ protected override void UpdateValue(MqttMsgPublishEventArgs e) {
+ this.GetBool = (Encoding.UTF8.GetString(e.Message).ToLower() == "on") ? true : false;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Power.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Power.cs
new file mode 100644
index 0000000..d796e1b
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Power.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using Dashboard.Connector;
+
+namespace Dashboard.Sensor {
+ class Power : ASensor {
+ public Power(Dictionary settings, String name, ADataBackend backend) : base(settings, name, backend) {
+ this.GetBool = true;
+ this.GetFloat = 0.0f;
+ this.GetInt = 0;
+ this.Datatypes = Types.Float;
+ }
+
+ protected override Boolean UpdateValue(MqttEventArgs e) {
+ this.GetFloat = Single.Parse(e.Message, new CultureInfo("en-US"));
+ return true;
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Switch.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Switch.cs
new file mode 100644
index 0000000..7537208
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Switch.cs
@@ -0,0 +1,16 @@
+using System;
+using System.Collections.Generic;
+using Dashboard.Connector;
+
+namespace Dashboard.Sensor {
+ class Switch : ASensor {
+ public Switch(Dictionary settings, String name, ADataBackend backend) : base(settings, name, backend) {
+ this.Datatypes = Types.Bool;
+ }
+
+ protected override Boolean UpdateValue(MqttEventArgs e) {
+ this.GetBool = (e.Message.ToLower() == "on") ? true : false;
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Temperatur.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Temperatur.cs
new file mode 100644
index 0000000..702b871
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Sensor/Temperatur.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Text;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace Dashboard.Sensor {
+ class Temperatur : ASensor {
+ public Temperatur(Dictionary settings) : base(settings) {
+ this.GetBool = true;
+ this.GetFloat = 0.0f;
+ this.GetInt = 0;
+ this.Datatypes = Types.Float;
+ }
+
+ protected override void UpdateValue(MqttMsgPublishEventArgs e) {
+ this.GetFloat = Single.Parse(Encoding.UTF8.GetString(e.Message), new CultureInfo("en-US"));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/ATracings.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/ATracings.cs
new file mode 100644
index 0000000..e400472
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/ATracings.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using Dashboard.Sensor;
+
+namespace Dashboard.Tracings {
+ public abstract class ATracings {
+ protected ASensor sensor;
+ protected Dictionary settings;
+ protected Dictionary sensors;
+
+ public ATracings(ASensor sensor, Dictionary settings) {
+ this.sensor = sensor;
+ this.sensor.Update += this.SensorUpdate;
+ this.settings = settings;
+ }
+ public ATracings(Dictionary sensors, Dictionary settings) {
+ this.sensors = sensors;
+ foreach(KeyValuePair sensor in this.sensors) {
+ sensor.Value.Update += this.SensorsUpdate;
+ }
+ this.settings = settings;
+ }
+
+ protected abstract void SensorsUpdate(ASensor sender, EventArgs e);
+ protected abstract void SensorUpdate(ASensor sender, EventArgs e);
+ public abstract Panel GetPanel();
+ internal static ATracings GetInstance(String v, Dictionary sensorList, Dictionary dictionary) {
+ String object_sensor = "Dashboard.Tracings." + Char.ToUpper(v[0]) + v.Substring(1);
+ Type t = null;
+ try {
+ t = Type.GetType(object_sensor, true);
+ } catch (TypeLoadException) {
+ throw new ArgumentException("tracings.ini: " + v + " is not a Tracing");
+ }
+ if (dictionary["sensor"].Contains(",")) {
+ Dictionary sensors = new Dictionary();
+ String[] sensors_name = dictionary["sensor"].Split(',');
+ foreach (String item in sensors_name) {
+ sensors.Add(item, sensorList[item.ToLower()]);
+ }
+ return (ATracings)t.GetConstructor(new Type[] { typeof(Dictionary), typeof(Dictionary) }).Invoke(new Object[] { sensors, dictionary });
+ } else {
+ return (ATracings)t.GetConstructor(new Type[] { typeof(ASensor), typeof(Dictionary) }).Invoke(new Object[] { sensorList[dictionary["sensor"].ToLower()], dictionary });
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Graph.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Graph.cs
new file mode 100644
index 0000000..7bb1d2e
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Graph.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Forms;
+using Dashboard.Sensor;
+using OxyPlot;
+using OxyPlot.Axes;
+using OxyPlot.Series;
+using OxyPlot.WindowsForms;
+
+namespace Dashboard.Tracings {
+ class Graph : ATracings, IDisposable {
+ private Queue> hist = new Queue>();
+ private Dictionary>> hists = new Dictionary>>();
+ private Dictionary hists_last = new Dictionary();
+ private Int32 Chart_Items;
+ private PlotView plot = new PlotView { BackColor = System.Drawing.Color.White };
+ private PlotModel Model = new PlotModel();
+ private Boolean multi;
+ private Single MaximumDrawn = 1;
+
+ private String[] colors = { "255,255,0,0","255,230,230,0", "255,0,128,0", "255,0,0,255", "255,255,0,255", "255,255,128,0", "255,0,255,255", "255,158,255,128", "255,0,128,255", "255,0,0,0" };
+
+ public Graph(ASensor sensor, Dictionary settings) : base(sensor, settings) {
+ this.Chart_Items = (settings.Keys.Contains("items")) ? Int32.Parse(settings["items"]) : 1000;
+ this.multi = false;
+ }
+
+ public Graph(Dictionary sensors, Dictionary settings) : base(sensors, settings) {
+ this.Chart_Items = (settings.Keys.Contains("items")) ? Int32.Parse(settings["items"]) : 1000;
+ this.multi = true;
+ }
+
+ public override Panel GetPanel() {
+ Panel panel = new Panel { BorderStyle = BorderStyle.FixedSingle };
+
+ this.Model.Axes.Add(new DateTimeAxis { Position = AxisPosition.Bottom, AbsoluteMinimum = DateTimeAxis.ToDouble(DateTime.Now), AbsoluteMaximum = DateTimeAxis.ToDouble(DateTime.Now.AddMinutes(1)), IsZoomEnabled = false });
+ this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false });
+ if (this.multi) {
+ Int32 i = 0;
+ foreach (KeyValuePair item in this.sensors) {
+ LineSeries l = new LineSeries { Color = OxyColor.Parse(this.colors[i++ % this.colors.Length]), TrackerKey = item.Value.Name };
+ if (item.Value.Title != "") {
+ l.Title = item.Value.Title;
+ }
+ this.Model.Series.Add(l);
+ }
+ } else {
+ LineSeries l = new LineSeries { Color = OxyColor.FromRgb(0, 0, 255) };
+ l.CanTrackerInterpolatePoints = true;
+ if (this.sensor.Title != "") {
+ l.Title = this.sensor.Title;
+ }
+ this.Model.Series.Add(l);
+ }
+
+ Int32 fieldWidth = 200;
+ if(this.multi) {
+ fieldWidth = (this.sensors.Count * 200) + (this.sensors.Count-1)*6;
+ }
+
+ this.plot.Location = new System.Drawing.Point(0, 0);
+ this.plot.Size = new System.Drawing.Size(fieldWidth, 200);
+ this.plot.Dock = DockStyle.Fill;
+ this.plot.Model = this.Model;
+ panel.Controls.Add(this.plot);
+
+ panel.Size = new System.Drawing.Size(fieldWidth, 200);
+ return panel;
+ }
+ protected override void SensorUpdate(ASensor sender, EventArgs e) {
+ Single v = 0;
+ switch (sender.Datatypes) {
+ case ASensor.Types.Bool: v = sender.GetBool ? 1 : 0; break;
+ case ASensor.Types.Int: v = sender.GetInt; break;
+ case ASensor.Types.Float: v = sender.GetFloat; break;
+ }
+ this.hist.Enqueue(new Tuple(sender.Timestamp, v));
+ if (this.MaximumDrawn < v) {
+ this.MaximumDrawn = v;
+ }
+ if (this.hist.Count > this.Chart_Items) {
+ this.hist.Dequeue();
+ }
+ if (this.Model.Series.Count != 0) {
+ this.plot.BeginInvoke((MethodInvoker)delegate {
+ this.Model.Axes[1].Maximum = this.MaximumDrawn * 1.1;
+ this.Model.Axes[1].AbsoluteMaximum = this.MaximumDrawn * 1.1;
+ this.Model.Axes[0].AbsoluteMaximum = DateTimeAxis.ToDouble(sender.Timestamp);
+ ((LineSeries)this.Model.Series[0]).Points.Clear();
+ try {
+ foreach(Tuple temp in this.hist) {
+ ((LineSeries)this.Model.Series[0]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(temp.Item1),temp.Item2));
+ }
+ this.Model.InvalidatePlot(true);
+ } catch(Exception) { };
+ });
+ }
+ }
+
+ protected override void SensorsUpdate(ASensor sender, EventArgs e) {
+ Single v = 0;
+ if (!this.hists.ContainsKey(sender.Name)) {
+ this.hists.Add(sender.Name, new Queue>());
+ this.hists_last.Add(sender.Name, 0);
+ }
+ switch (sender.Datatypes) {
+ case ASensor.Types.Bool:
+ v = sender.GetBool ? 1 : 0;
+ break;
+ case ASensor.Types.Int:
+ v = sender.GetInt;
+ break;
+ case ASensor.Types.Float:
+ v = sender.GetFloat;
+ break;
+ }
+ this.hists_last[sender.Name] = v;
+ foreach (KeyValuePair>> item in this.hists) {
+ item.Value.Enqueue(new Tuple(sender.Timestamp, this.hists_last[item.Key]));
+ if (this.MaximumDrawn < this.hists_last[item.Key]) {
+ this.MaximumDrawn = this.hists_last[item.Key];
+ }
+ if (item.Value.Count > this.Chart_Items) {
+ item.Value.Dequeue();
+ }
+ }
+ foreach (Series item in this.Model.Series) {
+ if (this.hists.ContainsKey(item.TrackerKey)) {
+ this.plot.BeginInvoke((MethodInvoker)delegate {
+ try {
+ this.Model.Axes[1].Maximum = this.MaximumDrawn * 1.1;
+ this.Model.Axes[1].AbsoluteMaximum = this.MaximumDrawn * 1.1;
+ this.Model.Axes[0].AbsoluteMaximum = DateTimeAxis.ToDouble(sender.Timestamp);
+ ((LineSeries)item).Points.Clear();
+ foreach (Tuple temp in this.hists[item.TrackerKey]) {
+ ((LineSeries)item).Points.Add(new DataPoint(DateTimeAxis.ToDouble(temp.Item1), temp.Item2));
+ }
+ this.Model.InvalidatePlot(true);
+ } catch (Exception) { };
+ });
+ }
+ }
+ }
+
+ public void Dispose() {
+ ((LineSeries)this.Model.Series[0]).Points.Clear();
+ this.Model = null;
+ this.hist.Clear();
+ this.hist = null;
+ this.plot.Dispose();
+ }
+
+
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Meter.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Meter.cs
new file mode 100644
index 0000000..928f9aa
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Meter.cs
@@ -0,0 +1,71 @@
+using System.Collections.Generic;
+using Dashboard.Sensor;
+using System;
+using System.Windows.Forms;
+using System.Linq;
+using System.Globalization;
+
+namespace Dashboard.Tracings {
+ class Meter : ATracings {
+ protected Int32 DisplayItems;
+ protected Queue DisplayAverage = new Queue();
+ protected Label label1;
+ protected Label label2;
+
+ public Meter(ASensor sensor, Dictionary settings) : base(sensor, settings) {
+ this.DisplayItems = (settings.Keys.Contains("items")) ? Int32.Parse(settings["items"]) : 1000;
+
+ this.label1 = new Label();
+ this.label2 = new Label();
+ }
+ public override Panel GetPanel() {
+ Panel panel = new Panel() {
+ BorderStyle = BorderStyle.FixedSingle,
+ Size = new System.Drawing.Size(200, 100)
+ };
+
+ this.label1 = new Label() {
+ Font = new System.Drawing.Font("Lucida Sans Typewriter", 27.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((Byte)(0))),
+ Location = new System.Drawing.Point(0, 0),
+ Size = new System.Drawing.Size(200, 43),
+ Text = "",
+ TextAlign = System.Drawing.ContentAlignment.TopCenter
+ };
+ panel.Controls.Add(this.label1);
+
+ this.label2 = new Label() {
+ AutoSize = true,
+ Location = new System.Drawing.Point(0, 50),
+ Size = new System.Drawing.Size(96, 13),
+ Text = ""
+ };
+ panel.Controls.Add(this.label2);
+
+
+ return panel;
+ }
+
+ protected override void SensorsUpdate(ASensor sender, EventArgs e) {
+ throw new NotImplementedException();
+ }
+
+ protected override void SensorUpdate(ASensor sender, EventArgs e) {
+ String value = "";
+ switch(sender.Datatypes) {
+ case ASensor.Types.Bool: this.DisplayAverage.Enqueue((sender.GetBool) ? 1 : 0); value = sender.GetBool.ToString(new CultureInfo("de-DE")); break;
+ case ASensor.Types.Int: this.DisplayAverage.Enqueue(sender.GetInt); value = sender.GetInt.ToString(); break;
+ case ASensor.Types.Float: this.DisplayAverage.Enqueue(sender.GetFloat); value = sender.GetFloat.ToString(new CultureInfo("de-DE")); break;
+ }
+ if(this.DisplayAverage.Count > this.DisplayItems) {
+ this.DisplayAverage.Dequeue();
+ }
+ Single average = this.DisplayAverage.Sum() / this.DisplayAverage.Count();
+ this.label1.BeginInvoke((MethodInvoker)delegate {
+ this.label1.Text = value;
+ });
+ this.label2.BeginInvoke((MethodInvoker)delegate {
+ this.label2.Text = "Durchschnitt: " + Math.Round(average, 2);
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/PowerMeter.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/PowerMeter.cs
new file mode 100644
index 0000000..3a4b3ca
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/PowerMeter.cs
@@ -0,0 +1,42 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Windows.Forms;
+using Dashboard.Sensor;
+
+namespace Dashboard.Tracings {
+ class Powermeter : Meter {
+ public Powermeter(ASensor sensor, Dictionary settings) : base(sensor, settings) {
+ }
+ protected override void SensorUpdate(ASensor sender, EventArgs e) {
+ String value = "";
+ switch (sender.Datatypes) {
+ case ASensor.Types.Bool:
+ this.DisplayAverage.Enqueue((sender.GetBool) ? 1 : 0);
+ value = sender.GetBool.ToString(new CultureInfo("de-DE"));
+ break;
+ case ASensor.Types.Int:
+ this.DisplayAverage.Enqueue(sender.GetInt);
+ value = sender.GetInt.ToString();
+ break;
+ case ASensor.Types.Float:
+ this.DisplayAverage.Enqueue(sender.GetFloat);
+ value = sender.GetFloat.ToString(new CultureInfo("de-DE"));
+ break;
+ }
+ if (this.DisplayAverage.Count > this.DisplayItems) {
+ this.DisplayAverage.Dequeue();
+ }
+ Single average = this.DisplayAverage.Sum() / this.DisplayAverage.Count();
+ try {
+ this.label1.BeginInvoke((MethodInvoker)delegate {
+ this.label1.Text = value + " W";
+ });
+ this.label2.BeginInvoke((MethodInvoker)delegate {
+ this.label2.Text = "Durchschnitt: " + Math.Round(average, 2) + " W";
+ });
+ } catch (Exception) { }
+ }
+ }
+}
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Switcher.cs b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Switcher.cs
new file mode 100644
index 0000000..83679f4
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/Tracings/Switcher.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Windows.Forms;
+using Dashboard.Connector;
+using Dashboard.Sensor;
+
+namespace Dashboard.Tracings {
+ class Switcher : ATracings {
+ private Label label;
+ private Button button1;
+ private Button button2;
+
+ public Switcher(ASensor sensor, Dictionary settings) : base(sensor, settings) {
+ this.label = new Label();
+ this.button1 = new Button();
+ this.button2 = new Button();
+ }
+
+ public override Panel GetPanel() {
+ Panel panel = new Panel() {
+ BorderStyle = BorderStyle.FixedSingle,
+ Size = new System.Drawing.Size(200, 100)
+ };
+
+ this.label = new Label() {
+ AutoSize = true,
+ Location = new System.Drawing.Point(69, 16),
+ Size = new System.Drawing.Size(35, 13),
+ Text = ""
+ };
+ panel.Controls.Add(this.label);
+
+ this.button1 = new Button() {
+ BackColor = System.Drawing.Color.FromArgb(0, 192, 0),
+ Location = new System.Drawing.Point(94, 67),
+ Name = "on",
+ Size = new System.Drawing.Size(45, 23),
+ Text = "ON",
+ UseVisualStyleBackColor = false
+ };
+ this.button1.Click += this.ButtonClicker;
+ panel.Controls.Add(this.button1);
+
+ this.button2 = new Button() {
+ BackColor = System.Drawing.Color.Red,
+ Location = new System.Drawing.Point(145, 67),
+ Name = "off",
+ Size = new System.Drawing.Size(45, 23),
+ Text = "OFF",
+ UseVisualStyleBackColor = false
+ };
+ this.button2.Click += this.ButtonClicker;
+ panel.Controls.Add(this.button2);
+
+ return panel;
+ }
+
+ private void ButtonClicker(Object sender, EventArgs e) {
+ Button b = (Button)sender;
+ if (b.Name == "on") {
+ this.sensor.SetBool(true);
+ } else if(b.Name == "off") {
+ this.sensor.SetBool(false);
+ }
+ }
+
+ protected override void SensorUpdate(ASensor sender, EventArgs e) {
+ this.label.BeginInvoke((MethodInvoker)delegate {
+ this.label.Text = sender.GetBool?"Eingeschaltet":"Ausgeschaltet";
+ });
+ this.button1.BeginInvoke((MethodInvoker)delegate {
+ this.button1.Enabled = !sender.GetBool;
+ });
+ this.button2.BeginInvoke((MethodInvoker)delegate {
+ this.button2.Enabled = sender.GetBool;
+ });
+ }
+
+ protected override void SensorsUpdate(ASensor sender, EventArgs e) {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Dashboard.exe b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Dashboard.exe
new file mode 100644
index 0000000..e190e87
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Dashboard.exe differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/LitJson.dll b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/LitJson.dll
new file mode 100644
index 0000000..f00f11f
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/LitJson.dll differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/M2Mqtt.Net.dll b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/M2Mqtt.Net.dll
new file mode 100644
index 0000000..154580d
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/M2Mqtt.Net.dll differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.WindowsForms.dll b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.WindowsForms.dll
new file mode 100644
index 0000000..4bde2bd
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.WindowsForms.dll differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.dll b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.dll
new file mode 100644
index 0000000..388e1dc
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/OxyPlot.dll differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils.dll b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils.dll
new file mode 100644
index 0000000..28f5d3d
Binary files /dev/null and b/Mqtt-Dashboard/Mqtt-Dashboard/bin/Release/Utils.dll differ
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/packages.config b/Mqtt-Dashboard/Mqtt-Dashboard/packages.config
new file mode 100644
index 0000000..ee578a6
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/sensor.ini.example b/Mqtt-Dashboard/Mqtt-Dashboard/sensor.ini.example
new file mode 100644
index 0000000..bb9c314
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/sensor.ini.example
@@ -0,0 +1,24 @@
+[Thinkpad]
+topic=zway/wohnzimmer/thinkpad/power
+type=Power
+polling=10
+
+[Tv]
+topic=zway/wohnzimmer/tV/power
+type=Power
+polling=10
+
+[Kühlschrank]
+topic=zway/küche/kuehlschrank/power
+type=Power
+polling=10
+
+[TvSW]
+topic=zway/wohnzimmer/tV/switch
+type=switch
+polling=10
+
+;[Ventilator]
+;topic=zway/power/test/wVentilator
+;type=Power
+;polling=10
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/settings.ini.example b/Mqtt-Dashboard/Mqtt-Dashboard/settings.ini.example
new file mode 100644
index 0000000..ed05fa8
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/settings.ini.example
@@ -0,0 +1,3 @@
+[mqtt]
+type=mqtt
+server=localhost
\ No newline at end of file
diff --git a/Mqtt-Dashboard/Mqtt-Dashboard/tracings.ini.example b/Mqtt-Dashboard/Mqtt-Dashboard/tracings.ini.example
new file mode 100644
index 0000000..d0ad8f0
--- /dev/null
+++ b/Mqtt-Dashboard/Mqtt-Dashboard/tracings.ini.example
@@ -0,0 +1,45 @@
+[ThinkpadMeter]
+sensor=Thinkpad
+type=PowerMeter
+items=100
+
+[TvMeter]
+sensor=Tv
+type=PowerMeter
+items=100
+
+[KühlschrankrMeter]
+sensor=Kühlschrank
+type=PowerMeter
+items=100
+
+[ThinkpadGraph]
+sensor=Thinkpad
+type=Graph
+items=100
+
+[TvGraph]
+sensor=Tv
+type=Graph
+items=100
+
+[KühlschrankGraph]
+sensor=Kühlschrank
+type=Graph
+items=100
+
+[TvSWMeter]
+sensor=TvSW
+type=Switcher
+items=100
+
+;[VentilatorGraph]
+;sensor=Ventilator
+;type=Graph
+;items=100
+
+;[VentilatorMeter]
+;sensor=Ventilator
+;type=Meter
+;unit=W
+;items=100
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.sln b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.sln
new file mode 100644
index 0000000..8ea20d1
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.sln
@@ -0,0 +1,31 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mqtt-SWB-Dashboard", "Mqtt-SWB-Dashboard\Mqtt-SWB-Dashboard.csproj", "{324B2308-7C6E-4F16-8764-7C2F8C342B6A}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {324B2308-7C6E-4F16-8764-7C2F8C342B6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {324B2308-7C6E-4F16-8764-7C2F8C342B6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {324B2308-7C6E-4F16-8764-7C2F8C342B6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {324B2308-7C6E-4F16-8764-7C2F8C342B6A}.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
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {8640C2B5-61E7-4C20-8E37-28A9543423B7}
+ EndGlobalSection
+EndGlobal
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.config b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.config
new file mode 100644
index 0000000..731f6de
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml
new file mode 100644
index 0000000..e67d8be
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml.cs
new file mode 100644
index 0000000..c7d79b2
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/App.xaml.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace Mqtt_SWB_Dashboard {
+ ///
+ /// Interaktionslogik für "App.xaml"
+ ///
+ public partial class App : Application {
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Device.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Device.cs
new file mode 100644
index 0000000..95074df
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Device.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Globalization;
+using LitJson;
+
+namespace Mqtt_SWB_Dashboard.Helper {
+ class Device {
+
+ public enum DevType {
+ State,
+ Consumption,
+ Production
+ }
+
+ public Device(JsonData data, DevType type) {
+ this.TimeStamp = new DateTime();
+ this.Power = 0;
+ this.Comul = 0;
+ this.Status = false;
+ this.Production = 0;
+ this.Type = type;
+ this.Update(data, type);
+ }
+
+ public Device(JsonData data) {
+ this.TimeStamp = DateTime.Parse(data["TimeStamp"].ToString(), new CultureInfo("en-US"));
+ this.Status = data["Status"].ToString() == "true" ? true : false;
+ this.Production = Double.Parse(data["Production"].ToString());
+ this.Type = (DevType)Int32.Parse(data["Type"].ToString());
+ this.Power = Double.Parse(data["Power"].ToString());
+ this.Comul = Double.Parse(data["Comul"].ToString());
+ }
+
+ public DateTime TimeStamp { get; private set; }
+ public Boolean Status { get; private set; }
+ public Double Production { get; private set; }
+ public DevType Type { get; private set; }
+ public Double Power { get; private set; }
+ public Double Comul { get; private set; }
+
+ internal void Update(JsonData data, DevType type) {
+ this.TimeStamp = DateTime.Parse(data["timestamp"].ToString());
+ if (type == DevType.State) {
+ this.Status = data["status"].ToString() == "active" ? true : false;
+ }
+ if (type == DevType.Consumption) {
+ this.Power = Double.Parse(data["power"].ToString());
+ this.Comul = Double.Parse(data["energyCumul"].ToString());
+ }
+ if (type == DevType.Production) {
+ this.Power = Double.Parse(data["power"].ToString());
+ this.Comul = Double.Parse(data["energyCumulative"].ToString());
+ this.Production = Double.Parse(data["productionCumulative"].ToString());
+ }
+ }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Household.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Household.cs
new file mode 100644
index 0000000..47e301d
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Household.cs
@@ -0,0 +1,105 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using LitJson;
+
+namespace Mqtt_SWB_Dashboard.Helper {
+ class Household {
+
+ public SortedDictionary Devices { get; private set; }
+ public DateTime Active { get; private set; }
+ public Boolean Connected { get; private set; }
+
+ public Household(String did, Device device) {
+ this.Active = DateTime.Now;
+ this.Devices = new SortedDictionary {
+ { did, device }
+ };
+ }
+
+ public Household(JsonData data) {
+ this.Devices = new SortedDictionary();
+ if (data.Keys.Contains("Devices")) {
+ foreach (KeyValuePair item in data["Devices"]) {
+ this.Devices.Add(item.Key, new Device(item.Value));
+ }
+ }
+ if(data.Keys.Contains("Connected")) {
+ this.Connected = Boolean.Parse(data["Connected"].ToString());
+ if (this.Connected) {
+ this.Active = DateTime.Now;
+ }
+ }
+ if(data.Keys.Contains("Active")) {
+ this.Active = DateTime.Parse(data["Active"].ToString(), new CultureInfo("en-US"));
+ }
+ }
+
+ public void PutDevice(String did, JsonData data, Device.DevType dtype) {
+ this.Active = DateTime.Now;
+ if (this.Devices.Keys.Contains(did)) {
+ this.Devices[did].Update(data, dtype);
+ } else {
+ this.Devices.Add(did, new Device(data, dtype));
+ }
+ }
+
+ internal Int32 GetActive() {
+ Int32 ret = 0;
+ foreach (KeyValuePair item in this.Devices) {
+ if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10)) {
+ ret++;
+ }
+ }
+ return ret;
+ }
+
+ internal Double GetPower() {
+ Double ret = 0;
+ foreach (KeyValuePair item in this.Devices) {
+ if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10) && item.Value.Type != Device.DevType.Production) {
+ ret += item.Value.Power;
+ }
+ }
+ return ret;
+ }
+
+ internal Double GetAllPower() {
+ Double ret = 0;
+ foreach (KeyValuePair item in this.Devices) {
+ if (item.Value.Type != Device.DevType.Production) {
+ ret += item.Value.Power;
+ }
+ }
+ return ret;
+ }
+
+ internal Double GetColum() {
+ Double ret = 0;
+ foreach (KeyValuePair item in this.Devices) {
+ if (item.Value.TimeStamp > DateTime.Now.AddMinutes(-10) && item.Value.Type != Device.DevType.Production) {
+ ret += item.Value.Comul;
+ }
+ }
+ return ret;
+ }
+
+ internal Double GetAllColum() {
+ Double ret = 0;
+ foreach (KeyValuePair item in this.Devices) {
+ if (item.Value.Type != Device.DevType.Production) {
+ ret += item.Value.Comul;
+ }
+ }
+ return ret;
+ }
+
+ internal void PutConnection(JsonData data) {
+ this.Connected = Boolean.Parse(data["Connected"].ToString());
+ if(this.Connected) {
+ this.Active = DateTime.Now;
+ }
+ }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Raspi.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Raspi.cs
new file mode 100644
index 0000000..3445a39
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Helper/Raspi.cs
@@ -0,0 +1,35 @@
+using System;
+using LitJson;
+
+namespace Mqtt_SWB_Dashboard.Helper {
+ class Raspi {
+
+ public Raspi(JsonData data) {
+ PutStatus(data);
+ if(data.Keys.Contains("Connected")) {
+ this.Connected = Boolean.Parse(data["Connected"].ToString());
+ }
+ if (data.Keys.Contains("Uptime")) {
+ this.Uptime = Double.Parse(data["Uptime"].ToString());
+ }
+ }
+
+ public Boolean Connected { get; private set; }
+ public Double Uptime { get; private set; }
+
+ internal void PutStatus(JsonData data) {
+ if (data.Keys.Contains("message")) {
+ if (data["message"].Keys.Contains("status")) {
+ this.Connected = (data["message"]["status"].ToString() == "disconnected") ? false : true;
+ if (!this.Connected) {
+ this.Uptime = 0;
+ }
+ }
+ if (data["message"].Keys.Contains("uptime")) {
+ this.Uptime = Double.Parse(data["message"]["uptime"].ToString());
+ this.Connected = true;
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml
new file mode 100644
index 0000000..4b53fbf
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml.cs
new file mode 100644
index 0000000..19c04f9
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/MainWindow.xaml.cs
@@ -0,0 +1,56 @@
+using BlubbFish.Utils;
+using System;
+using System.Globalization;
+using System.Windows;
+
+namespace Mqtt_SWB_Dashboard {
+ ///
+ /// Interaktionslogik für MainWindow.xaml
+ ///
+ public partial class MainWindow : Window {
+ private Stats s;
+
+ public MainWindow() {
+ InitializeComponent();
+ CultureInfo info = new CultureInfo("de-DE");
+ info.NumberFormat.NumberDecimalSeparator = ".";
+ CultureInfo.DefaultThreadCurrentCulture = info;
+ CultureInfo.DefaultThreadCurrentUICulture = info;
+ System.Threading.Thread.CurrentThread.CurrentCulture = info;
+ System.Threading.Thread.CurrentThread.CurrentUICulture = info;
+ LanguageProperty.OverrideMetadata(typeof(FrameworkElement), new FrameworkPropertyMetadata(System.Windows.Markup.XmlLanguage.GetLanguage(CultureInfo.CurrentCulture.IetfLanguageTag)));
+
+ try {
+ String broker = InIReader.GetInstance("settings.ini").GetValue("general", "broker");
+ this.Dispatcher.BeginInvoke((Action)(() => {
+ this.connectedTo.Text = "Connected to: " + broker;
+ }));
+ this.s = new Stats(new Mosquitto(broker));
+ this.s.UpdatedConsumption += this.S_UpdatedConsumption;
+ this.S_UpdatedConsumption(this.s, null);
+ } catch(Exception e) {
+ MessageBox.Show(e.Message+"\n"+e.StackTrace, "Some Shit goes fucking wrong!");
+ Application.Current.Shutdown(1);
+ }
+ }
+
+ private void S_UpdatedConsumption(Stats sender, EventArgs e) {
+ this.Dispatcher.BeginInvoke((Action)(() => {
+ this.countHouses.Text = sender.GetNumberHouseholds();
+ this.countDevices.Text = sender.GetNumberDevices();
+ this.countRaspis.Text = sender.GetNumberRaspis();
+ this.maxRaspi.Text = sender.GetMostRaspiUptime();
+ this.avgUptime.Text = sender.GetAvgRaspiUptime();
+ Tuple power = sender.GetCurrentPower();
+ this.countPower.Text = power.Item1 + "W / " + power.Item2 + "W";
+ Tuple colum = sender.GetCurrentColum();
+ this.countColum.Text = colum.Item1.ToString("F1") + "kW / " + colum.Item2.ToString("F1") + "kW";
+ ((Models.PowerChartModel)this.DataContext).AddPower(power, colum);
+ }));
+ }
+
+ private void OnClosed(Object sender, EventArgs e) {
+ this.s.Dispose();
+ }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Models/PowerChartModel.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Models/PowerChartModel.cs
new file mode 100644
index 0000000..0621698
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Models/PowerChartModel.cs
@@ -0,0 +1,79 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using OxyPlot;
+using OxyPlot.Axes;
+using OxyPlot.Series;
+
+namespace Mqtt_SWB_Dashboard.Models {
+ public class PowerChartModel : INotifyPropertyChanged {
+ private Double MaximumDrawnL = 5;
+ private Double MaximumDrawnR = 5;
+
+ public event PropertyChangedEventHandler PropertyChanged;
+
+ public PowerChartModel() {
+ Instance = this;
+ this.Model = new PlotModel { Title = "Stromverbrauch" };
+ this.Model.Axes.Add(new DateTimeAxis { Position = AxisPosition.Bottom, AbsoluteMinimum = DateTimeAxis.ToDouble(DateTime.Now), AbsoluteMaximum = DateTimeAxis.ToDouble(DateTime.Now.AddMinutes(1)), IsZoomEnabled = false });
+ this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Left, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false });
+ this.Model.Axes.Add(new LinearAxis { Position = AxisPosition.Right, AbsoluteMinimum = 0, Minimum = 0, AbsoluteMaximum = 1, IsZoomEnabled = false, Key = "Right" });
+
+ this.Model.Series.Add(new LineSeries { Title = "Active [W]", Color = OxyColor.FromRgb(0, 150, 0) });
+ this.Model.Series.Add(new LineSeries { Title = "Seen [W]", Color = OxyColor.FromRgb(0, 255, 0) });
+ this.Model.Series.Add(new LineSeries { Title = "Active [kW]", Color = OxyColor.FromRgb(0, 0, 150), YAxisKey= "Right" });
+ this.Model.Series.Add(new LineSeries { Title = "Seen [kW]", Color = OxyColor.FromRgb(0, 0, 255), YAxisKey = "Right" });
+ this.RaisePropertyChanged("Model");
+ }
+
+ internal void AddPower(Tuple power, Tuple colum) {
+ if((power.Item1 == 0 && power.Item2 == 0) || (colum.Item1 == 0 && colum.Item2 == 0)) {
+ return;
+ }
+ ((LineSeries)this.Model.Series[0]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), power.Item1));
+ ((LineSeries)this.Model.Series[1]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), power.Item2));
+ ((LineSeries)this.Model.Series[2]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), colum.Item1));
+ ((LineSeries)this.Model.Series[3]).Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), colum.Item2));
+
+ if (this.MaximumDrawnL < power.Item1) {
+ this.MaximumDrawnL = power.Item1;
+ }
+ if (this.MaximumDrawnL < power.Item2) {
+ this.MaximumDrawnL = power.Item2;
+ }
+ if (this.MaximumDrawnR < colum.Item1) {
+ this.MaximumDrawnR = colum.Item1;
+ }
+ if (this.MaximumDrawnR < colum.Item2) {
+ this.MaximumDrawnR = colum.Item2;
+ }
+ //this.Model.Axes[1].Minimum = 0;
+ //this.Model.Axes[2].Minimum = 0;
+ this.Model.Axes[1].Maximum = this.MaximumDrawnL * 1.1;
+ this.Model.Axes[1].AbsoluteMaximum = this.MaximumDrawnL * 1.1;
+
+ this.Model.Axes[2].Maximum = this.MaximumDrawnR * 1.05;
+ this.Model.Axes[2].AbsoluteMaximum = this.MaximumDrawnR * 1.05;
+
+ this.Model.Axes[0].AbsoluteMaximum = DateTimeAxis.ToDouble(DateTime.Now);
+
+ this.TotalNumberOfPoints++;
+ this.RaisePropertyChanged("TotalNumberOfPoints");
+
+ this.Model.InvalidatePlot(true);
+ }
+ protected void RaisePropertyChanged(String property) {
+ this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property));
+ }
+
+ public PlotModel Model { get; private set; }
+ public Int32 TotalNumberOfPoints { get; private set; }
+ public static PowerChartModel Instance { get; private set; }
+
+
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mosquitto.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mosquitto.cs
new file mode 100644
index 0000000..597b5f5
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mosquitto.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Diagnostics;
+using System.Text.RegularExpressions;
+
+namespace Mqtt_SWB_Dashboard {
+ class Mosquitto : IDisposable {
+ private Process p;
+ private String message;
+
+ public delegate void MqttMessage(Object sender, MqttEventArgs e);
+ public event MqttMessage MessageIncomming;
+
+ public Mosquitto(String broker) {
+ //mosquitto_sub --cafile ca.pem --cert cert.pem --key cert.key -h swb.broker.flex4grid.eu -p 8883 -t /# -v
+ this.message = "";
+ this.p = new Process();
+ this.p.StartInfo.FileName = "mosquitto_sub.exe";
+ this.p.StartInfo.Arguments = "--cafile ca.pem --cert cert.pem --key cert.key -h "+broker+" -p 8883 -t /# -v -d";
+ this.p.StartInfo.CreateNoWindow = true;
+ this.p.StartInfo.UseShellExecute = false;
+ this.p.StartInfo.RedirectStandardOutput = true;
+ this.p.StartInfo.RedirectStandardError = true;
+ this.p.OutputDataReceived += this.P_OutputDataReceived;
+ this.p.ErrorDataReceived += this.P_ErrorDataReceived;
+ this.p.Start();
+ this.p.BeginOutputReadLine();
+ }
+
+ private void P_ErrorDataReceived(Object sender, DataReceivedEventArgs e) {
+ if (e.Data != null) {
+ throw new NotImplementedException(e.Data);
+ }
+ }
+
+ private void P_OutputDataReceived(Object sender, DataReceivedEventArgs e) {
+ if (e.Data != null) {
+ if (e.Data.StartsWith("Client mosqsub")) {
+ if (this.message != "" && this.message.IndexOf(" received PUBLISH ") > 0) {
+ MatchCollection matches = (new Regex("^Client mosqsub\\|.*received PUBLISH \\(.*,.*,.*,.*, '(.*)'.*\\)\\)\n[^ ]* (.*)$", RegexOptions.IgnoreCase | RegexOptions.Singleline)).Matches(this.message);
+ String topic = matches[0].Groups[1].Value;
+ String message = matches[0].Groups[2].Value.Trim();
+ this.MessageIncomming?.Invoke(this, new MqttEventArgs(message, topic));
+ }
+ this.message = e.Data + "\n";
+ } else {
+ this.message += e.Data + "\n";
+ }
+ }
+ }
+
+ #region IDisposable Support
+ private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
+
+ protected virtual void Dispose(Boolean disposing) {
+ if (!this.disposedValue) {
+ if (disposing) {
+ this.p.CancelOutputRead();
+ this.p.Kill();
+ this.p.Close();
+ }
+ this.p = null;
+ this.disposedValue = true;
+ }
+ }
+
+ ~Mosquitto() {
+ Dispose(false);
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+ class MqttEventArgs : EventArgs {
+ public MqttEventArgs() : base() { }
+ public MqttEventArgs(String message, String topic) {
+ this.Topic = topic;
+ this.Message = message;
+ this.Date = DateTime.Now;
+ }
+
+ public String Topic { get; private set; }
+ public String Message { get; private set; }
+ public DateTime Date { get; private set; }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.csproj b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.csproj
new file mode 100644
index 0000000..7037cb8
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard.csproj
@@ -0,0 +1,122 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {324B2308-7C6E-4F16-8764-7C2F8C342B6A}
+ WinExe
+ Mqtt_SWB_Dashboard
+ Mqtt-SWB-Dashboard
+ v4.6.1
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\LitJson.0.9.0\lib\LitJson.dll
+
+
+ ..\packages\OxyPlot.Core.1.0.0\lib\net45\OxyPlot.dll
+
+
+ ..\packages\OxyPlot.Wpf.1.0.0\lib\net45\OxyPlot.Wpf.dll
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+
+
+
+ {fac8ce64-bf13-4ece-8097-aeb5dd060098}
+ Utils
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/AssemblyInfo.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..1746479
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/AssemblyInfo.cs
@@ -0,0 +1,57 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// 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("Mqtt-SWB-Dashboard")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Mqtt-SWB-Dashboard")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// 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)]
+
+//Um mit dem Erstellen lokalisierbarer Anwendungen zu beginnen, legen Sie
+//ImCodeVerwendeteKultur in der .csproj-Datei
+//in einer fest. Wenn Sie in den Quelldateien beispielsweise Deutsch
+//(Deutschland) verwenden, legen Sie auf \"de-DE\" fest. Heben Sie dann die Auskommentierung
+//des nachstehenden NeutralResourceLanguage-Attributs auf. Aktualisieren Sie "en-US" in der nachstehenden Zeile,
+//sodass es mit der UICulture-Einstellung in der Projektdatei übereinstimmt.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //Speicherort der designspezifischen Ressourcenwörterbücher
+ //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
+ // oder in den Anwendungsressourcen-Wörterbüchern nicht gefunden werden kann.)
+ ResourceDictionaryLocation.SourceAssembly //Speicherort des generischen Ressourcenwörterbuchs
+ //(wird verwendet, wenn eine Ressource auf der Seite nicht gefunden wird,
+ // designspezifischen Ressourcenwörterbuch nicht gefunden werden kann.)
+)]
+
+
+// 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.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: NeutralResourcesLanguage("")]
+
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.Designer.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..ffb2064
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.Designer.cs
@@ -0,0 +1,62 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion: 4.0.30319.42000
+//
+// Änderungen an dieser Datei können fehlerhaftes Verhalten verursachen und gehen verloren, wenn
+// der Code neu generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace Mqtt_SWB_Dashboard.Properties {
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder-Klasse
+ // über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der Option /str erneut aus, oder erstellen Sie Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if ((resourceMan == null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Mqtt_SWB_Dashboard.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenlookups, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.resx b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.resx
new file mode 100644
index 0000000..af7dbeb
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.Designer.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..d9f1ade
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace Mqtt_SWB_Dashboard.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.settings b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.settings
new file mode 100644
index 0000000..033d7a5
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Stats.cs b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Stats.cs
new file mode 100644
index 0000000..5d707d3
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/Stats.cs
@@ -0,0 +1,318 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text.RegularExpressions;
+using LitJson;
+using Mqtt_SWB_Dashboard.Helper;
+
+namespace Mqtt_SWB_Dashboard {
+ internal class Stats : IDisposable {
+ private SortedDictionary households = new SortedDictionary();
+ private SortedDictionary raspis = new SortedDictionary();
+ private Mosquitto mosquitto;
+
+ public delegate void UpdateMessage(Stats sender, EventArgs e);
+ public event UpdateMessage UpdatedConsumption;
+
+ public Stats(Mosquitto mosquitto) {
+ LoadSavedData();
+ this.mosquitto = mosquitto;
+ this.mosquitto.MessageIncomming += this.Mosquitto_MessageIncomming;
+ }
+
+ private void LoadSavedData() {
+ if (File.Exists("household.json")) {
+ try {
+ JsonData data = JsonMapper.ToObject(File.ReadAllText("household.json"));
+ foreach (KeyValuePair item in data) {
+ this.households.Add(item.Key, new Household(item.Value));
+ }
+ } catch (Exception) { }
+ }
+ if (File.Exists("raspi.json")) {
+ JsonData data = JsonMapper.ToObject(File.ReadAllText("raspi.json"));
+ foreach (KeyValuePair item in data) {
+ this.raspis.Add(item.Key, new Raspi(item.Value));
+ }
+ }
+ }
+
+ /*
+ *
+ */
+ private void Mosquitto_MessageIncomming(Object sender, MqttEventArgs e) {
+ if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/groups/.*").Success) {
+ this.LvcMessages(e);
+ } else if (Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/hosts/.*/status").Success ||
+ e.Topic == "/flex4grid/VersionControl/LocalGateway/status") {
+ this.RaspiStatus(e);
+ } else if(Regex.Match(e.Topic, "/flex4grid/VersionControl/LocalGateway/hosts/.*/logs/gateway/plugs/gateway_plugs_1").Success) {
+ this.RaspiLogs(e);
+ } else if (Regex.Match(e.Topic, "/flex4grid/v1/households/.*/connection").Success) {
+ this.HouseholdStatus(e);
+ } else if (Regex.Match(e.Topic, "/flex4grid/v1/households/.*/consumption").Success ||
+ Regex.Match(e.Topic, "/flex4grid/v1/households/.*/device/consumption").Success ||
+ Regex.Match(e.Topic, "/flex4grid/v1/households/.*/device/state").Success) {
+ this.HouseholdConsumption(e);
+ } else if (Regex.Match(e.Topic, "/flex4grid/v1/households/.*/devices/state/request").Success ||
+ Regex.Match(e.Topic, "/flex4grid/v1/households/.*/devices/state/response").Success) {
+ this.DeviceStates(e);
+ } else if (Regex.Match(e.Topic, "/flex4grid/v1/households/.*/device/actuate").Success) {
+ this.DeviceSwitching(e);
+ } else {
+ System.Windows.MessageBox.Show(e.Topic + " " + e.Message);
+ }
+ }
+
+ #region Mqtt-Message Parser
+
+ ///
+ /// LogMessages eines Raspis
+ ///
+ ///
+ private void RaspiLogs(MqttEventArgs e) {
+ // /flex4grid/VersionControl/LocalGateway/hosts/F4G-B827EB705A1F/logs/gateway/plugs/gateway_plugs_1 2017-09-17T20:31:13.081733337Z
+ // [main] MQTTPulbisher.onConnectionLost() lost connection to the broker: pingresp not received, disconnecting
+ }
+
+ ///
+ /// Nachrichten des LVC-Images
+ ///
+ ///
+ private void LvcMessages(MqttEventArgs e) {
+ //"/flex4grid/VersionControl/LocalGateway/groups/BONN_1 {\n \"src\": \"fc.flex4grid.eu\",\n \"type\": \"config_update\",\n..." -> Nachricht vom Lvc Image
+ }
+
+ ///
+ /// Nachricht wenn ein gerät umgeschaltet werden soll von der App aus.
+ ///
+ ///
+ private void DeviceSwitching(MqttEventArgs e) {
+ // "/flex4grid/v1/households/911b2e25-8ac4-4ad0-90ae-c8cff42c4224/device/actuate {"command":"OFF","deviceId":"6","timestamp":"2017-09-17T16:41:50.963000Z"}" -> App Gerät Schalten
+ }
+
+ ///
+ /// Status der Geräte von der App aus abfragen und den Schaltzustand antworten
+ ///
+ ///
+ private void DeviceStates(MqttEventArgs e) {
+ // "/flex4grid/v1/households/911b2e25-8ac4-4ad0-90ae-c8cff42c4224/devices/state/request {"timestamp": "2017-09-17T16:40:46.456000Z"}" -> App Gerät Abfragen
+ // "/flex4grid/v1/households/911b2e25-8ac4-4ad0-90ae-c8cff42c4224/devices/state/response {"2": "active", "3": "active", "4": "active", "5": "active", "6": "active", "timestamp": "2017-09-17T14:43:52.536676Z"}" -> App Gerät Antworten
+ }
+
+ ///
+ /// Schaltstatus, Stromverbrauch und Produktion von PowerPlugs
+ ///
+ ///
+ private void HouseholdConsumption(MqttEventArgs e) {
+ Match m = Regex.Match(e.Topic, "/flex4grid/v1/households/([^/]*)/(consumption|device/(consumption|state))");
+ String id = m.Groups[1].Value;
+ Device.DevType dtype = Device.DevType.Consumption;
+ if (m.Groups[2].Value == "consumption") {
+ dtype = Device.DevType.Production;
+ } else if (m.Groups[3].Value == "consumption") {
+ dtype = Device.DevType.Consumption;
+ } else if (m.Groups[3].Value == "state") {
+ dtype = Device.DevType.State;
+ }
+ try {
+ JsonData data = JsonMapper.ToObject(e.Message);
+ String did = data["id"].ToString();
+ if(id.Contains("911b2e25") && did == "3") {
+
+ }
+ if (this.households.Keys.Contains(id)) {
+ this.households[id].PutDevice(did, data, dtype);
+ } else {
+ this.households.Add(id, new Household(did, new Device(data, dtype)));
+ }
+ this.UpdatedConsumption?.Invoke(this, null);
+ } catch (Exception) {
+ }
+ }
+
+ ///
+ /// Nachricht ob ein Haushalt (gateway_plugs_1) verbunden ist (Vermutlich vom Master)
+ ///
+ ///
+ private void HouseholdStatus(MqttEventArgs e) {
+ Match m = Regex.Match(e.Topic, "/flex4grid/v1/households/([^/]*)/connection");
+ String id = m.Groups[1].Value;
+ try {
+ JsonData data = JsonMapper.ToObject(e.Message.Replace("connected", "Connected"));
+ if (this.households.Keys.Contains(id)) {
+ this.households[id].PutConnection(data);
+ } else {
+ this.households.Add(id, new Household(data));
+ }
+ this.UpdatedConsumption?.Invoke(this, null);
+ } catch (Exception) {
+ }
+ }
+
+ ///
+ /// Nachricht ob ein Raspi Verbunden ist (liefert die lvc Werte?)
+ ///
+ ///
+ private void RaspiStatus(MqttEventArgs e) {
+ try {
+ JsonData data = JsonMapper.ToObject(e.Message);
+ String id = data["src"].ToString();
+ if (this.raspis.Keys.Contains(id)) {
+ this.raspis[id].PutStatus(data);
+ } else {
+ this.raspis.Add(id, new Raspi(data));
+ }
+ this.UpdatedConsumption?.Invoke(this, null);
+ } catch (Exception) {
+ }
+ }
+
+ #endregion
+
+ #region Statistics Output
+
+ internal String GetNumberDevices() {
+ Int32 active = 0;
+ Int32 all = 0;
+ try {
+ foreach (KeyValuePair item in this.households) {
+ active += item.Value.GetActive();
+ all += item.Value.Devices.Count;
+ }
+ } catch(Exception) {
+ return "0 / 0";
+ }
+ return active.ToString() + " / " + all.ToString();
+ }
+
+ internal String GetNumberHouseholds() {
+ Int32 active = 0;
+ Int32 ping = 0;
+ Int32 all = this.households.Count;
+ try {
+ foreach (KeyValuePair item in this.households) {
+ if (item.Value.Active > DateTime.Now.AddMinutes(-10)) {
+ ping++;
+ }
+ if (item.Value.Connected) {
+ active++;
+ }
+ }
+ } catch (Exception) {
+ return "0 / 0 / 0";
+ }
+ return ping + " / " + active + " / " + all;
+ }
+
+ internal Tuple GetCurrentPower() {
+ Double active = 0;
+ Double all = 0;
+ try {
+ foreach (KeyValuePair item in this.households) {
+ active += item.Value.GetPower();
+ all += item.Value.GetAllPower();
+ }
+ } catch(Exception) {
+ return new Tuple(0d, 0d);
+ }
+ return new Tuple(active, all);
+ }
+
+ internal Tuple GetCurrentColum() {
+ Double active = 0;
+ Double all = 0;
+ try {
+ foreach (KeyValuePair item in this.households) {
+ active += item.Value.GetColum();
+ all += item.Value.GetAllColum();
+ }
+ } catch(Exception) {
+ return new Tuple(0d, 0d);
+ }
+ return new Tuple(active, all);
+ }
+
+ internal String GetNumberRaspis() {
+ Int32 active = 0;
+ Int32 all = this.raspis.Count;
+ try {
+ foreach (KeyValuePair item in this.raspis) {
+ if(item.Value.Connected) {
+ active++;
+ }
+ }
+ } catch (Exception) {
+ return "0 / 0";
+ }
+ return active.ToString() + " / " + all.ToString();
+ }
+
+ internal String GetAvgRaspiUptime() {
+ Double values = 0;
+ Int32 count = 0;
+ try {
+ foreach (KeyValuePair item in this.raspis) {
+ if (item.Value.Connected) {
+ values += item.Value.Uptime;
+ count++;
+ }
+ }
+ } catch (Exception) {
+ return "0t 00:00:00";
+ }
+ return new TimeSpan((Int64)((values/count) * 10000000d)).ToString("%d't 'hh':'mm':'ss");
+ }
+
+ internal String GetMostRaspiUptime() {
+ Double max = 0;
+ String name="";
+ try {
+ foreach (KeyValuePair item in this.raspis) {
+ if (item.Value.Connected && max < item.Value.Uptime) {
+ max = item.Value.Uptime;
+ name = item.Key;
+ }
+ }
+ } catch (Exception) {
+ return "- / 0";
+ }
+ return name + " / " + new TimeSpan((Int64)(max * 10000000d)).ToString("%d't 'hh':'mm':'ss");
+ }
+
+ #endregion
+
+ #region IDisposable Support
+ private Boolean disposedValue = false; // Dient zur Erkennung redundanter Aufrufe.
+
+ protected virtual void Dispose(Boolean disposing) {
+ if (!this.disposedValue) {
+ if (disposing) {
+ this.mosquitto.MessageIncomming -= this.Mosquitto_MessageIncomming;
+ JsonWriter writer = new JsonWriter {
+ PrettyPrint = true
+ };
+ JsonMapper.ToJson(this.households, writer);
+ File.WriteAllText("household.json", writer.ToString());
+ writer.Reset();
+ JsonMapper.ToJson(this.raspis, writer);
+ File.WriteAllText("raspi.json", writer.ToString());
+ this.mosquitto.Dispose();
+ }
+ this.mosquitto = null;
+ this.disposedValue = true;
+ }
+ }
+
+ ~Stats() {
+ Dispose(false);
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/LitJson.dll b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/LitJson.dll
new file mode 100644
index 0000000..f00f11f
Binary files /dev/null and b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/LitJson.dll differ
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Mqtt-SWB-Dashboard.exe b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Mqtt-SWB-Dashboard.exe
new file mode 100644
index 0000000..b775cc4
Binary files /dev/null and b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Mqtt-SWB-Dashboard.exe differ
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.Wpf.dll b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.Wpf.dll
new file mode 100644
index 0000000..04d8c34
Binary files /dev/null and b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.Wpf.dll differ
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.dll b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.dll
new file mode 100644
index 0000000..388e1dc
Binary files /dev/null and b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/OxyPlot.dll differ
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Utils.dll b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Utils.dll
new file mode 100644
index 0000000..7edc0ad
Binary files /dev/null and b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/bin/Release/Utils.dll differ
diff --git a/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/packages.config b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/packages.config
new file mode 100644
index 0000000..d70f7b9
--- /dev/null
+++ b/Mqtt-SWB-Dashboard/Mqtt-SWB-Dashboard/packages.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MqttToTelegram/MqttToTelegram.sln b/MqttToTelegram/MqttToTelegram.sln
new file mode 100644
index 0000000..fc19be2
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25420.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MqttToTelegram", "MqttToTelegram\MqttToTelegram.csproj", "{89077643-B472-419F-8EAB-56B9E2D13ABC}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {89077643-B472-419F-8EAB-56B9E2D13ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {89077643-B472-419F-8EAB-56B9E2D13ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {89077643-B472-419F-8EAB-56B9E2D13ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {89077643-B472-419F-8EAB-56B9E2D13ABC}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/MqttToTelegram/MqttToTelegram/App.config b/MqttToTelegram/MqttToTelegram/App.config
new file mode 100644
index 0000000..88fa402
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MqttToTelegram/MqttToTelegram/Mqtt.cs b/MqttToTelegram/MqttToTelegram/Mqtt.cs
new file mode 100644
index 0000000..e0ccfa0
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/Mqtt.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Text;
+using uPLibrary.Networking.M2Mqtt;
+using uPLibrary.Networking.M2Mqtt.Messages;
+
+namespace MqttToTelegram {
+ class Mqtt {
+ private static Mqtt instance;
+ private MqttClient client;
+
+ private Mqtt() {
+ client = new MqttClient("129.26.160.65");
+ byte code = client.Connect(System.Guid.NewGuid().ToString());
+ client.MqttMsgPublishReceived += MessageResieved;
+ }
+
+ private void MessageResieved(System.Object sender, MqttMsgPublishEventArgs e) {
+ Console.WriteLine("Received = " + Encoding.UTF8.GetString(e.Message) + " on Topic " + e.Topic);
+ }
+
+ public static Mqtt Instance {
+ get {
+ if(instance == null) {
+ instance = new Mqtt();
+ }
+ return instance;
+ }
+ }
+ public void Subscripe(string[] topics) {
+ byte[] qos = new byte[topics.Length];
+ for(int i=0;i
+
+
+
+ Debug
+ AnyCPU
+ {89077643-B472-419F-8EAB-56B9E2D13ABC}
+ Exe
+ Properties
+ MqttToTelegram
+ MqttToTelegram
+ v4.5.2
+ 512
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ ..\packages\M2Mqtt.4.3.0.0\lib\net45\M2Mqtt.Net.dll
+ True
+
+
+ ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+
+
+
+
+
+ ..\packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll
+ True
+
+
+
+
+
+
+
+
+ ..\packages\Telegram.Bot.13.1.0\lib\netstandard1.1\Telegram.Bot.dll
+ True
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MqttToTelegram/MqttToTelegram/Program.cs b/MqttToTelegram/MqttToTelegram/Program.cs
new file mode 100644
index 0000000..799b7d0
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/Program.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MqttToTelegram {
+ class Program {
+ static void Main(string[] args) {
+ Mqtt.Instance.Subscripe(new string[]{ "#"});
+ Messenger.Instance.bla();
+ while(true) {
+ System.Threading.Thread.Sleep(100);
+ }
+ }
+ }
+}
diff --git a/MqttToTelegram/MqttToTelegram/Properties/AssemblyInfo.cs b/MqttToTelegram/MqttToTelegram/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..2574141
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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("MqttToTelegram")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("MqttToTelegram")]
+[assembly: AssemblyCopyright("Copyright © 2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. 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("89077643-b472-419f-8eab-56b9e2d13abc")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/MqttToTelegram/MqttToTelegram/Telegram.cs b/MqttToTelegram/MqttToTelegram/Telegram.cs
new file mode 100644
index 0000000..b18422e
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/Telegram.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Telegram.Bot;
+
+namespace MqttToTelegram {
+ class Messenger {
+ private static Messenger instance;
+ private TelegramBotClient bot;
+
+ private Messenger() {
+ bot = new TelegramBotClient("");
+ bot.OnMessage += Bot_OnMessage;
+ }
+
+ private void Bot_OnMessage(Object sender, Telegram.Bot.Args.MessageEventArgs e) {
+ Console.WriteLine("Telegram: " + e.Message.Text);
+ }
+
+ public static Messenger Instance {
+ get {
+ if(instance == null) {
+ instance = new Messenger();
+ }
+ return instance;
+ }
+ }
+
+ public void bla() {
+ bot.StartReceiving();
+ }
+ }
+}
diff --git a/MqttToTelegram/MqttToTelegram/packages.config b/MqttToTelegram/MqttToTelegram/packages.config
new file mode 100644
index 0000000..709db32
--- /dev/null
+++ b/MqttToTelegram/MqttToTelegram/packages.config
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TimeKeeper/Arduino/Display/Display.ino b/TimeKeeper/Arduino/Display/Display.ino
new file mode 100644
index 0000000..92a426f
--- /dev/null
+++ b/TimeKeeper/Arduino/Display/Display.ino
@@ -0,0 +1,85 @@
+#include
+
+#define MAX_STORE_DATA 8
+
+void setup() {
+ Serial.begin(9600);
+ Serial.println("Init....");
+ Rb.init();
+ Serial.println("Init finished!");
+}
+
+String store[MAX_STORE_DATA];
+int count = 0;
+
+String msg;
+char c;
+void loop() {
+ if (Serial.available()) {
+ c = Serial.read();
+ if (c == '\n') {
+ parse(msg);
+ msg = "";
+ } else {
+ msg += c;
+ }
+ }
+}
+
+void parse(String text) {
+ text.trim();
+ String action = "";
+ String value = "";
+ if (text.indexOf("=") != -1) {
+ action = text.substring(0, text.indexOf("="));
+ value = text.substring(text.indexOf("=") + 1);
+ doJob(action, value);
+ }
+}
+int job = -1;
+int online = -1;
+void doJob(String task, String value) {
+ if (task == "job") {
+ char b = '!';
+ uint32_t co = 0;
+ if(value.toInt() == 1) {
+ b = 'F'; //Fraunhofer
+ co = 0x00FF22; //Fraunhofer Color
+ } else if(value.toInt() == 2) {
+ b = 'R'; //Rwth Aachen
+ co = 0x00539F; //Rwth Color
+ }
+ job = value.toInt();
+ Rb.fillRectangle(1, 2, 7, 6, 0x000000);
+ Rb.drawChar(b, 1, 1, co);
+ } else if(task == "online") {
+ Rb.setPixelXY(0,7,value.toInt()==0?0xFF0000:0x00FF00);
+ online = value.toInt();
+ } else if(task == "getJob") {
+ Serial.println("setJob="+String(job));
+ } else if(task == "getOnline") {
+ Serial.println("setOnline="+String(online));
+ } else if(task == "tag") {
+ Rb.fillRectangle(0, 0, 8, 1, 0x000000);
+ if(count < MAX_STORE_DATA) {
+ count++;
+ store[count-1] = String("tag="+value);
+ //Serial.println("d: "+ store[count-1]);
+ //Serial.println("d: "+ String(count));
+ }
+ Rb.fillRectangle(7-(count-1), 0, 8, 1, 0xFFFF00);
+ } else if(task == "getStoreCount") {
+ Serial.println("hasCount="+String(count));
+ } else if(task == "getStoreData") {
+ if(count > 0) {
+ Serial.print("dataStore=");
+ for(int i=0; i < count-1; i++) {
+ Serial.print(store[i]+"|");
+ }
+ Serial.println(store[count-1]);
+ count = 0;
+ Rb.fillRectangle(0, 0, 8, 1, 0x000000);
+ }
+ }
+}
+
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2.sln b/TimeKeeper/Arduino/Zeit/Zeit-V2.sln
new file mode 100644
index 0000000..b115c5e
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zeit-V2", "Zeit-V2\Zeit-V2.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x86 = Debug|x86
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.ino b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.ino
new file mode 100644
index 0000000..5817b2d
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.ino
@@ -0,0 +1,20 @@
+#define DEBUG_FLAG true
+
+#include "programm.h"
+ProgClass* p;
+
+void setup() {
+ Serial.begin(9600);
+ p = new ProgClass(&Serial);
+ #if defined(DEBUG_FLAG) && DEBUG_FLAG
+ Serial.println("Init loading!");
+ #endif
+ p->loadFromDisplay();
+ #if defined(DEBUG_FLAG) && DEBUG_FLAG
+ Serial.println("Init finished!");
+ #endif
+}
+
+void loop() {
+ p->loop();
+}
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj
new file mode 100644
index 0000000..3ba3a93
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj
@@ -0,0 +1,92 @@
+
+
+
+
+ Debug
+ Win32
+
+
+ Release
+ Win32
+
+
+
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}
+ Zeit_V2
+ Zeit-V2
+
+
+
+ Application
+ true
+
+
+ MultiByte
+
+
+ Application
+ false
+
+
+ true
+ MultiByte
+
+
+
+
+
+
+
+
+
+
+
+
+ C:\Users\schell\Documents\Arduino\libraries\Ethernet2\src;D:\Programme\Arduino\hardware\arduino\avr\libraries\SoftwareSerial;C:\Users\schell\Documents\Arduino\libraries\Time;D:\Programme\Arduino\hardware\arduino\avr\libraries\SPI;$(IncludePath)
+
+
+
+ Level3
+ Disabled
+ true
+ D:\Programme\Arduino\libraries;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\libraries;D:\Programme\Visual Studio\Common7\IDE\Extensions\hunc4op4.xpd\Micro Platforms\default\debuggers;C:\Users\schell\Documents\Arduino\libraries;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\cores\arduino;C:\Users\schell\AppData\Local\arduino15\packages\arduino\hardware\avr\1.6.11\variants\standard;C:\Users\schell\Documents\Arduino\Zeit-V2\Zeit-V2;D:\Programme\Arduino\hardware\tools\avr/avr/include/;D:\Programme\Arduino\hardware\tools\avr//avr/include/avr/;D:\Programme\Arduino\hardware\tools\avr/lib\gcc\avr\4.8.1\include;%(AdditionalIncludeDirectories)
+ C:\Users\schell\Documents\Arduino\Zeit-V2\Zeit-V2\__vm\.Zeit-V2.vsarduino.h;%(ForcedIncludeFiles)
+ false
+ __AVR_ATmega328p__;__AVR_ATmega328P__;F_CPU=16000000L;ARDUINO=10607;ARDUINO_AVR_UNO;ARDUINO_ARCH_AVR;__cplusplus=201103L;%(PreprocessorDefinitions)
+
+
+ true
+
+
+
+
+ Level3
+ MaxSpeed
+ true
+ true
+ true
+
+
+ true
+ true
+ true
+
+
+
+
+ CppCode
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj.filters b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj.filters
new file mode 100644
index 0000000..500d044
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/Zeit-V2.vcxproj.filters
@@ -0,0 +1,40 @@
+
+
+
+
+ {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
+ cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
+
+
+ {93995380-89BD-4b04-88EB-625FBE52EBFB}
+ h;hh;hpp;hxx;hm;inl;inc;xsd
+
+
+ {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
+ rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
+
+
+
+
+
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+ Header Files
+
+
+
\ No newline at end of file
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/button.h b/TimeKeeper/Arduino/Zeit/Zeit-V2/button.h
new file mode 100644
index 0000000..6f379f8
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/button.h
@@ -0,0 +1,27 @@
+class ButtonClass {
+ private:
+ void init(void);
+ public:
+ ButtonClass(void);
+ bool check(uint8_t job);
+ uint8_t read(void);
+};
+
+
+ButtonClass::ButtonClass(void) {
+ this->init();
+}
+
+void ButtonClass::init(void) {
+ pinMode(2, INPUT_PULLUP);
+ pinMode(3, INPUT_PULLUP);
+}
+
+bool ButtonClass::check(uint8_t job) {
+ return ((digitalRead(2) == LOW && job != 1) || (digitalRead(3) == LOW && job != 2));
+}
+
+uint8_t ButtonClass::read(void){
+ return digitalRead(2)==LOW?1:2;
+}
+
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/display.h b/TimeKeeper/Arduino/Zeit/Zeit-V2/display.h
new file mode 100644
index 0000000..102973a
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/display.h
@@ -0,0 +1,59 @@
+#if !defined(DEBUG_FLAG)
+ #define DEBUG_FLAG false
+#endif
+
+#include
+#if DEBUG_FLAG
+ #include
+#endif
+
+class DispClass {
+ private:
+ SoftwareSerial* serD;
+ #if DEBUG_FLAG
+ HardwareSerial* _debug;
+ #endif
+ void init(void);
+ public:
+ #if DEBUG_FLAG
+ DispClass(HardwareSerial *debug);
+ #else
+ DispClass(void);
+ #endif
+ void print(String text);
+ void setTimeout(unsigned long timeout);
+ String readStringUntil(char terminator);
+};
+
+#if DEBUG_FLAG
+ DispClass::DispClass(HardwareSerial *debug) {
+ this->_debug = debug;
+ this->init();
+ }
+#else
+ DispClass::DispClass(void) {
+ this->init();
+ }
+#endif
+
+void DispClass::init(void) {
+ this->serD = new SoftwareSerial(7, 6);
+ this->serD->begin(9600);
+}
+
+void DispClass::print(String text) {
+ #if DEBUG_FLAG
+ this->_debug->println("d->: "+text);
+ #endif
+ this->serD->listen();
+ this->serD->println(text);
+}
+
+void DispClass::setTimeout(unsigned long timeout) {
+ this->serD->setTimeout(timeout);
+}
+
+String DispClass::readStringUntil(char terminator) {
+ return this->serD->readStringUntil(terminator);
+}
+
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/network.h b/TimeKeeper/Arduino/Zeit/Zeit-V2/network.h
new file mode 100644
index 0000000..221b690
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/network.h
@@ -0,0 +1,64 @@
+#if !defined(DEBUG_FLAG)
+ #define DEBUG_FLAG false
+#endif
+
+#include
+#include
+#if DEBUG_FLAG
+ #include
+#endif
+
+class NetClass {
+ private:
+ #if DEBUG_FLAG
+ HardwareSerial* _debug;
+ #endif
+ EthernetClass* e;
+ void init(void);
+ // Mac-Adress of the Ethernet-Shield
+ uint8_t mac[6] = { 0x90, 0xA2, 0xDA, 0x10, 0x4F, 0xA4 };
+ public:
+ #if DEBUG_FLAG
+ NetClass(HardwareSerial *debug);
+ #else
+ NetClass(void);
+ #endif
+};
+
+#if DEBUG_FLAG
+ NetClass::NetClass(HardwareSerial *debug) {
+ this->_debug = debug;
+ this->init();
+ }
+#else
+ NetClass::NetClass(void) {
+ this->init();
+ }
+#endif
+
+void NetClass::init(void) {
+ pinMode(10, OUTPUT);
+ digitalWrite(10, HIGH);
+ #if DEBUG_FLAG
+ this->_debug->println("Start Network!");
+ this->_debug->println("DHCP Request");
+ #endif
+ this->e = &Ethernet;
+ if (this->e->begin(mac) == 0) {
+ #if DEBUG_FLAG
+ this->_debug->println("DHCP Failed, Use Link-Local Adress");
+ #endif
+ this->e->begin(mac, IPAddress(169, 254, 1, 177), IPAddress(169, 254, 0, 1), IPAddress(255, 255, 0, 0));
+ }
+ #if DEBUG_FLAG
+ this->_debug->print("Ethernet Started! IP: ");
+ IPAddress ip = Ethernet.localIP();
+ for (byte thisByte = 0; thisByte < 4; thisByte++) {
+ // print the value of each byte of the IP address:
+ this->_debug->print(ip[thisByte], DEC);
+ this->_debug->print(".");
+ }
+ this->_debug->println();
+ #endif
+}
+
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/programm.h b/TimeKeeper/Arduino/Zeit/Zeit-V2/programm.h
new file mode 100644
index 0000000..7886a7c
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/programm.h
@@ -0,0 +1,194 @@
+#if !defined(DEBUG_FLAG)
+ #define DEBUG_FLAG false
+#endif
+
+#include
+#include
+#include
+#include "display.h"
+#include "network.h"
+#include "rfid.h"
+#include "button.h"
+
+class ProgClass {
+ private:
+ static const int MAX_STORE_DATA = 8;
+
+ HardwareSerial* _usb;
+ DispClass* disp;
+ NetClass* net;
+ RfidClass* rfid;
+ ButtonClass* bu;
+
+ int8_t _storeCount = -1;
+ int8_t _job = -1;
+ int8_t _online = -1;
+ bool _keep = false;
+ String _storeData[MAX_STORE_DATA];
+ String _cmsg;
+
+ void init(void);
+ void parse(String text);
+ bool keepAlive(void);
+ void doJob(String task, String value);
+
+ public:
+ ProgClass(HardwareSerial *usb);
+ void loop(void);
+ void loadFromDisplay(void);
+};
+
+ProgClass::ProgClass(HardwareSerial *usb) {
+ this->_usb = usb;
+ this->init();
+}
+
+void ProgClass::init(void) {
+ #if DEBUG_FLAG
+ this->_usb->println("Init....");
+ this->disp = new DispClass(this->_usb);
+ this->net = new NetClass(this->_usb);
+ #else
+ this->disp = new DispClass();
+ this->net = new NetClass();
+ #endif
+ this->rfid = new RfidClass();
+ this->bu = new ButtonClass();
+ this->_usb->println("t="+String(now()));
+}
+
+void ProgClass::loop(void) {
+ char c;
+ if (this->rfid->hasData()) {
+ if (this->rfid->allowed()) {
+ this->_online = this->_online == 1 ? 0 : 1;
+ this->doJob("tag", this->rfid->getData());
+ this->doJob("online", String(this->_online));
+ delay(1000);
+ }
+ this->rfid->clear();
+ }
+ if (this->_usb->available()) {
+ c = this->_usb->read();
+ if (c == '\n') {
+ this->parse(this->_cmsg);
+ this->_cmsg = "";
+ }
+ else {
+ this->_cmsg += c;
+ }
+ }
+ if (this->bu->check(this->_job)) {
+ this->_job = this->bu->read();
+ this->doJob("job", String(this->_job));
+ this->rfid->clear();
+ }
+}
+
+void ProgClass::loadFromDisplay(void) {
+ this->disp->setTimeout(1000);
+ this->disp->print("getJob=1");
+ this->parse(this->disp->readStringUntil('\n'));
+ this->disp->print("getOnline=1");
+ this->parse(this->disp->readStringUntil('\n'));
+ if (this->keepAlive()) {
+ this->disp->print("getStoreCount=1");
+ this->parse(this->disp->readStringUntil('\n'));
+ if (this->_storeCount > 0) {
+ this->disp->print("getStoreData=1");
+ this->parse(this->disp->readStringUntil('\n'));
+ }
+ }
+ if (this->keepAlive()) {
+ this->doJob("getStore", "1");
+ }
+}
+
+void ProgClass::parse(String text) {
+ #if DEBUG_FLAG
+ this->_usb->println("i<-: " + text);
+ #endif
+ text.trim();
+ String task = "";
+ String value = "";
+ if (text.indexOf("=") != -1) {
+ task = text.substring(0, text.indexOf("="));
+ value = text.substring(text.indexOf("=") + 1);
+ this->doJob(task, value);
+ }
+}
+
+bool ProgClass::keepAlive(void) {
+ this->_usb->setTimeout(1000);
+ this->_keep = false;
+ this->_usb->println("requestKeep=1");
+ String a = this->_usb->readStringUntil('\n');
+ if (a != "") {
+ this->parse(a);
+ }
+ return this->_keep;
+}
+
+void ProgClass::doJob(String task, String value) {
+ if (task == "tag") {
+ char hex[15];
+ value.toCharArray(hex, 14);
+ String answ = "tag=" + String(strtol(hex, NULL, 16));
+ answ += ";time=" + String(now());
+ answ += ";job=" + String(this->_job);
+ answ += ";online=" + String(this->_online);
+ if (this->keepAlive()) {
+ this->_usb->println(answ);
+ }
+ else {
+ this->disp->print(answ);
+ }
+ }
+ else if (task == "job") {
+ this->disp->print("job=" + value);
+ }
+ else if (task == "online") {
+ this->disp->print("online=" + value);
+ }
+ else if (task == "time") {
+ setTime(value.toInt());
+ this->_usb->println("t=" + String(now()));
+ }
+ else if (task == "setJob") {
+ this->_job = value.toInt();
+ }
+ else if (task == "setOnline") {
+ this->_online = value.toInt();
+ }
+ else if (task == "keep") {
+ this->_keep = true;
+ }
+ else if (task == "hasCount") {
+ this->_storeCount = value.toInt();
+ }
+ else if (task == "dataStore") {
+ int i = 0;
+ while (true) {
+ if (i == MAX_STORE_DATA) {
+ break;
+ }
+ if (value.indexOf('|') == -1) {
+ this->_storeData[i] = value;
+ i++;
+ break;
+ }
+ this->_storeData[i] = value.substring(0, value.indexOf('|'));
+ value = value.substring(value.indexOf('|') + 1);
+ i++;
+ }
+ this->_storeCount = i;
+ }
+ else if (task == "getStore") {
+ if (this->_storeCount > 0) {
+ for (int i = 0; i < this->_storeCount; i++) {
+ this->_usb->println(this->_storeData[i]);
+ }
+ this->_storeCount = 0;
+ }
+ }
+}
\ No newline at end of file
diff --git a/TimeKeeper/Arduino/Zeit/Zeit-V2/rfid.h b/TimeKeeper/Arduino/Zeit/Zeit-V2/rfid.h
new file mode 100644
index 0000000..57534b1
--- /dev/null
+++ b/TimeKeeper/Arduino/Zeit/Zeit-V2/rfid.h
@@ -0,0 +1,48 @@
+#include
+
+class RfidClass {
+ private:
+ SoftwareSerial* serD;
+ void init(void);
+ String rmsg;
+ public:
+ RfidClass(void);
+ bool hasData(void);
+ String getData(void);
+ bool allowed(void);
+ void clear(void);
+};
+
+RfidClass::RfidClass(void) {
+ this->init();
+}
+
+void RfidClass::init(void) {
+ this->serD = new SoftwareSerial (9, 8);
+ this->serD->begin(9600);
+}
+
+bool RfidClass::hasData(void) {
+ this->serD->listen();
+ if(this->serD->available()) {
+ this->rmsg += (char)this->serD->read();
+ }
+ if(this->rmsg.length() >= 14) {
+ this->rmsg = this->rmsg.substring(1,13);
+ return true;
+ }
+ return false;
+}
+
+String RfidClass::getData(void){
+ return this->rmsg;
+}
+
+bool RfidClass::allowed() {
+ return (this->rmsg == "0A006AB7AE79");
+}
+
+void RfidClass::clear(void) {
+ this->rmsg = "";
+}
+
diff --git a/TimeKeeper/TimeKeeper.sln b/TimeKeeper/TimeKeeper.sln
new file mode 100644
index 0000000..eecca72
--- /dev/null
+++ b/TimeKeeper/TimeKeeper.sln
@@ -0,0 +1,46 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.25123.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TimeKeeper", "TimeKeeper\TimeKeeper.csproj", "{25F58397-71CB-4298-979E-BAACE80C61CB}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "..\Utils\Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Zeit-V2", "Arduino\Zeit\Zeit-V2\Zeit-V2.vcxproj", "{C5F80730-F44F-4478-BDAE-6634EFC2CA88}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Debug|x86 = Debug|x86
+ Release|Any CPU = Release|Any CPU
+ Release|x86 = Release|x86
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Debug|x86.Build.0 = Debug|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Release|Any CPU.Build.0 = Release|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Release|x86.ActiveCfg = Release|Any CPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}.Release|x86.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}.Debug|x86.ActiveCfg = Debug|Any CPU
+ {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Debug|x86.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
+ {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|x86.ActiveCfg = Release|Any CPU
+ {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}.Release|x86.Build.0 = Release|Any CPU
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|Any CPU.ActiveCfg = Debug|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.ActiveCfg = Debug|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Debug|x86.Build.0 = Debug|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|Any CPU.ActiveCfg = Release|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.ActiveCfg = Release|Win32
+ {C5F80730-F44F-4478-BDAE-6634EFC2CA88}.Release|x86.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/TimeKeeper/TimeKeeper/Controller/CTray.cs b/TimeKeeper/TimeKeeper/Controller/CTray.cs
new file mode 100644
index 0000000..6f62748
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Controller/CTray.cs
@@ -0,0 +1,47 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TimeKeeper.Controller {
+ class Tray : OwnController {
+ private static View.Tray tray;
+ private static Controller.Window window;
+
+ override protected void init() {
+ tray = new View.Tray();
+ window = new Controller.Window();
+ }
+
+ ///
+ /// User klickt Doppelt auf das TrayIcon
+ ///
+ ///
+ ///
+ internal static void Click_Tray(object sender, EventArgs e) {
+ Click_Open(sender, e);
+ }
+
+ ///
+ /// User klickt auf den Eintrag Öffnen
+ ///
+ ///
+ ///
+ internal static void Click_Open(object sender, EventArgs e) {
+ window.execute();
+ }
+
+ ///
+ /// User klickt auf den Eintrag Beenden
+ ///
+ ///
+ ///
+ internal static void Click_Quit(object sender, EventArgs e) {
+ tray.Dispose();
+ Application.Exit();
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Controller/CWindow.cs b/TimeKeeper/TimeKeeper/Controller/CWindow.cs
new file mode 100644
index 0000000..713bd44
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Controller/CWindow.cs
@@ -0,0 +1,25 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TimeKeeper.Controller {
+ class Window : OwnController {
+ private static View.Window window;
+
+ public Window() {
+
+ }
+
+ override protected void init() {
+ window = new View.Window();
+ }
+
+ public static void FormClosed(object sender, FormClosedEventArgs e) {
+ window.Dispose();
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Database/DatabaseDriver.cs b/TimeKeeper/TimeKeeper/Database/DatabaseDriver.cs
new file mode 100644
index 0000000..82786cd
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Database/DatabaseDriver.cs
@@ -0,0 +1,469 @@
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Data;
+using System.Data.Common;
+using System.Data.SqlClient;
+using System.Data.SQLite;
+using MySql;
+using MySql.Data.Common;
+using MySql.Data.MySqlClient;
+using TimeKeeper.Exceptions;
+
+namespace TimeKeeper.Database {
+ public class DatabaseDriver : IDisposable {
+ ///
+ /// Current DB Engine
+ ///
+ public DatabaseEngine DatabaseEngine { get; protected set; }
+
+ ///
+ /// The database connection
+ ///
+ public DbConnection Connection { get; protected set; }
+
+ ///
+ /// Returns whether the Database connection is open
+ ///
+ public bool IsConnected {
+ get { return (Connection.State == ConnectionState.Open); }
+ }
+
+ ///
+ /// Returns the current conenction state of the database
+ ///
+ public ConnectionState State {
+ get { return Connection.State; }
+ }
+
+ ///
+ /// Gets the number of queries ran by this instance
+ ///
+ public int NumQueries = 0;
+
+ ///
+ /// Random, yes... But its used here when building queries dynamically
+ ///
+ protected static char Comma = ',';
+
+ ///
+ /// Indicates whether the disposed method was called
+ ///
+ protected bool IsDisposed = false;
+
+ ///
+ /// Constructor
+ ///
+ /// The string name, for the GetDatabaseEngine() method
+ /// The Database server IP Address
+ /// The Database server Port Number
+ /// The name of the database
+ /// A username, with database privliages
+ /// The password to the User
+ public DatabaseDriver(string Engine, string Host, int Port, string DatabaseName, string User, string Pass, DatabaseEngine[] allowedEngines) {
+ // Set class variables, and create a new connection builder
+ this.DatabaseEngine = GetDatabaseEngine(Engine);
+ DbConnectionStringBuilder Builder;
+
+ // Establish the connection
+ if(this.DatabaseEngine == DatabaseEngine.Sqlite && allowedEngines.Contains(DatabaseEngine.Sqlite)) {
+ // Create the connection
+ Builder = new SQLiteConnectionStringBuilder();
+ Builder.Add("Data Source", Path.Combine(StaticConfig.RootPath, DatabaseName + ".sqlite3"));
+ Connection = new SQLiteConnection(Builder.ConnectionString);
+ } else if(this.DatabaseEngine == DatabaseEngine.Mysql && allowedEngines.Contains(DatabaseEngine.Mysql)) {
+ // Create the connection
+ Builder = new MySqlConnectionStringBuilder();
+ Builder.Add("Server", Host);
+ Builder.Add("Port", Port);
+ Builder.Add("User ID", User);
+ Builder.Add("Password", Pass);
+ Builder.Add("Database", DatabaseName);
+ Builder.Add("Convert Zero Datetime", "true");
+ Connection = new MySqlConnection(Builder.ConnectionString);
+ } else {
+ throw new Exception("Invalid Database type.");
+ }
+ }
+
+ ///
+ /// Destructor
+ ///
+ ~DatabaseDriver() {
+ Dispose();
+ }
+
+ ///
+ /// Disposes the DB connection
+ ///
+ public void Dispose() {
+ if(Connection != null && !IsDisposed) {
+ try {
+ Connection.Close();
+ Connection.Dispose();
+ } catch(ObjectDisposedException) { }
+
+ IsDisposed = true;
+ }
+ }
+
+ ///
+ /// Opens the database connection
+ ///
+ public void Connect() {
+ if(Connection.State != ConnectionState.Open) {
+ try {
+ Connection.Open();
+ } catch(Exception e) {
+ throw new DbConnectException("Unable to etablish database connection", e);
+ }
+ }
+ }
+
+ ///
+ /// Closes the connection to the database
+ ///
+ public void Close() {
+ try {
+ if(Connection.State != ConnectionState.Closed)
+ Connection.Close();
+ } catch(ObjectDisposedException) { }
+ }
+
+ ///
+ /// Creates a new command to be executed on the database
+ ///
+ ///
+ public DbCommand CreateCommand(string QueryString) {
+ if(DatabaseEngine == Database.DatabaseEngine.Sqlite)
+ return new SQLiteCommand(QueryString, Connection as SQLiteConnection);
+ else
+ return new MySqlCommand(QueryString, Connection as MySqlConnection);
+ }
+
+ ///
+ /// Creates a DbParameter using the current Database engine's Parameter object
+ ///
+ ///
+ public DbParameter CreateParam() {
+ if(DatabaseEngine == Database.DatabaseEngine.Sqlite)
+ return (new SQLiteParameter() as DbParameter);
+ else
+ return (new MySqlParameter() as DbParameter);
+ }
+
+ ///
+ /// Queries the database, and returns a result set
+ ///
+ /// The SQL Statement to run on the database
+ ///
+ public List> Query(string Sql) {
+ return this.Query(Sql, new List());
+ }
+
+ ///
+ /// Queries the database, and returns a result set
+ ///
+ /// The SQL Statement to run on the database
+ /// Additional parameters are parameter values for the query.
+ /// The first parameter replaces @P0, second @P1 etc etc.
+ ///
+ ///
+ public List> Query(string Sql, params object[] Items) {
+ List Params = new List(Items.Length);
+ for(int i = 0; i < Items.Length; i++) {
+ DbParameter Param = this.CreateParam();
+ Param.ParameterName = "@P" + i;
+ Param.Value = Items[i];
+ Params.Add(Param);
+ }
+
+ return this.Query(Sql, Params);
+ }
+
+ ///
+ /// Queries the database, and returns a result set
+ ///
+ /// The SQL Statement to run on the database
+ /// A list of sql params to add to the command
+ ///
+ public List> Query(string Sql, List Params) {
+ // Create our Rows result
+ List> Rows = new List>();
+
+ // Increase Query Count
+ NumQueries++;
+
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql)) {
+ // Add params
+ foreach(DbParameter Param in Params)
+ Command.Parameters.Add(Param);
+
+ // Execute the query
+ using(DbDataReader Reader = Command.ExecuteReader()) {
+ // If we have rows, add them to the list
+ if(Reader.HasRows) {
+ // Add each row to the rows list
+ while(Reader.Read()) {
+ Dictionary Row = new Dictionary(Reader.FieldCount);
+ for(int i = 0; i < Reader.FieldCount; ++i)
+ Row.Add(Reader.GetName(i), Reader.GetValue(i));
+
+ Rows.Add(Row);
+ }
+ }
+
+ // Cleanup
+ Reader.Close();
+ }
+ }
+
+ // Return Rows
+ return Rows;
+ }
+
+ ///
+ /// Queries the database, and returns 1 row at a time until all rows are returned
+ ///
+ /// The SQL Statement to run on the database
+ ///
+ public IEnumerable> QueryReader(string Sql) {
+ // Increase Query Count
+ NumQueries++;
+
+ // Create the SQL Command, and execute the reader
+ using(DbCommand Command = this.CreateCommand(Sql))
+ using(DbDataReader Reader = Command.ExecuteReader()) {
+ // If we have rows, add them to the list
+ if(Reader.HasRows) {
+ // Add each row to the rows list
+ while(Reader.Read()) {
+ Dictionary Row = new Dictionary(Reader.FieldCount);
+ for(int i = 0; i < Reader.FieldCount; ++i)
+ Row.Add(Reader.GetName(i), Reader.GetValue(i));
+
+ yield return Row;
+ }
+ }
+
+ // Cleanup
+ Reader.Close();
+ }
+ }
+
+ ///
+ /// Executes a command, and returns 1 row at a time until all rows are returned
+ ///
+ /// The database command to execute the reader on
+ ///
+ public IEnumerable> QueryReader(DbCommand Command) {
+ // Increase Query Count
+ NumQueries++;
+
+ // Execute the query
+ using(Command)
+ using(DbDataReader Reader = Command.ExecuteReader()) {
+ // If we have rows, add them to the list
+ if(Reader.HasRows) {
+ // Add each row to the rows list
+ while(Reader.Read()) {
+ Dictionary Row = new Dictionary(Reader.FieldCount);
+ for(int i = 0; i < Reader.FieldCount; ++i)
+ Row.Add(Reader.GetName(i), Reader.GetValue(i));
+
+ yield return Row;
+ }
+ }
+
+ // Cleanup
+ Reader.Close();
+ }
+ }
+
+
+ ///
+ /// Executes a command, and returns the resulting rows
+ ///
+ /// The database command to execute the reader on
+ ///
+ public List> ExecuteReader(DbCommand Command) {
+ // Execute the query
+ List> Rows = new List>();
+
+ // Increase Query Count
+ NumQueries++;
+
+ using(Command)
+ using(DbDataReader Reader = Command.ExecuteReader()) {
+ // If we have rows, add them to the list
+ if(Reader.HasRows) {
+ // Add each row to the rows list
+ while(Reader.Read()) {
+ Dictionary Row = new Dictionary(Reader.FieldCount);
+ for(int i = 0; i < Reader.FieldCount; ++i)
+ Row.Add(Reader.GetName(i), Reader.GetValue(i));
+
+ Rows.Add(Row);
+ }
+ }
+
+ // Cleanup
+ Reader.Close();
+ }
+
+ // Return Rows
+ return Rows;
+ }
+
+ ///
+ /// Executes a statement on the database (Update, Delete, Insert)
+ ///
+ /// The SQL statement to be executes
+ /// Returns the number of rows affected by the statement
+ public int Execute(string Sql) {
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql))
+ return Command.ExecuteNonQuery();
+ }
+
+ ///
+ /// Executes a statement on the database (Update, Delete, Insert)
+ ///
+ /// The SQL statement to be executed
+ /// A list of Sqlparameters
+ /// Returns the number of rows affected by the statement
+ public int Execute(string Sql, List Params) {
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql)) {
+ // Increase Query Count
+ NumQueries++;
+
+ // Add params
+ foreach(DbParameter Param in Params)
+ Command.Parameters.Add(Param);
+
+ // Execute command, and dispose of the command
+ return Command.ExecuteNonQuery();
+ }
+ }
+
+ ///
+ /// Executes a statement on the database (Update, Delete, Insert)
+ ///
+ /// The SQL statement to be executed
+ /// Additional parameters are parameter values for the query.
+ /// The first parameter replaces @P0, second @P1 etc etc.
+ ///
+ /// Returns the number of rows affected by the statement
+ public int Execute(string Sql, params object[] Items) {
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql)) {
+ // Add params
+ for(int i = 0; i < Items.Length; i++) {
+ DbParameter Param = this.CreateParam();
+ Param.ParameterName = "@P" + i;
+ Param.Value = Items[i];
+ Command.Parameters.Add(Param);
+ }
+
+ // Increase Query Count
+ NumQueries++;
+
+ // Execute command, and dispose of the command
+ return Command.ExecuteNonQuery();
+ }
+ }
+
+ ///
+ /// Executes the query, and returns the first column of the first row in the result
+ /// set returned by the query. Additional columns or rows are ignored.
+ ///
+ /// The SQL statement to be executed
+ ///
+ public object ExecuteScalar(string Sql) {
+ // Increase Query Count
+ NumQueries++;
+
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql))
+ return Command.ExecuteScalar();
+ }
+
+ ///
+ /// Executes the query, and returns the first column of the first row in the result
+ /// set returned by the query. Additional columns or rows are ignored.
+ ///
+ /// The SQL statement to be executed
+ /// A list of Sqlparameters
+ ///
+ public object ExecuteScalar(string Sql, List Params) {
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql)) {
+ // Increase Query Count
+ NumQueries++;
+
+ // Add params
+ foreach(DbParameter Param in Params)
+ Command.Parameters.Add(Param);
+
+ // Execute command, and dispose of the command
+ return Command.ExecuteScalar();
+ }
+ }
+
+ ///
+ /// Executes the query, and returns the first column of the first row in the result
+ /// set returned by the query. Additional columns or rows are ignored.
+ ///
+ /// The SQL statement to be executed
+ ///
+ ///
+ public object ExecuteScalar(string Sql, params object[] Items) {
+ // Create the SQL Command
+ using(DbCommand Command = this.CreateCommand(Sql)) {
+ // Add params
+ for(int i = 0; i < Items.Length; i++) {
+ DbParameter Param = this.CreateParam();
+ Param.ParameterName = "@P" + i;
+ Param.Value = Items[i];
+ Command.Parameters.Add(Param);
+ }
+
+ // Increase Query Count
+ NumQueries++;
+
+ // Execute command, and dispose of the command
+ return Command.ExecuteScalar();
+ }
+ }
+
+ ///
+ /// Begins a new database transaction
+ ///
+ ///
+ public DbTransaction BeginTransaction() {
+ return Connection.BeginTransaction();
+ }
+
+ ///
+ /// Begins a new database transaction
+ ///
+ ///
+ ///
+ public DbTransaction BeginTransaction(IsolationLevel Level) {
+ return Connection.BeginTransaction(Level);
+ }
+
+ ///
+ /// Converts a database string name to a DatabaseEngine type.
+ ///
+ ///
+ ///
+ public static DatabaseEngine GetDatabaseEngine(string Name) {
+ return ((DatabaseEngine)Enum.Parse(typeof(DatabaseEngine), Name, true));
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Database/DatabaseEngine.cs b/TimeKeeper/TimeKeeper/Database/DatabaseEngine.cs
new file mode 100644
index 0000000..9e8aeac
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Database/DatabaseEngine.cs
@@ -0,0 +1,8 @@
+namespace TimeKeeper.Database
+{
+ public enum DatabaseEngine
+ {
+ Sqlite,
+ Mysql,
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Database/SQL/MySQL.Install.sql b/TimeKeeper/TimeKeeper/Database/SQL/MySQL.Install.sql
new file mode 100644
index 0000000..24e0ea5
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Database/SQL/MySQL.Install.sql
@@ -0,0 +1,98 @@
+-- phpMyAdmin SQL Dump
+-- version 3.4.11.1deb2+deb7u2
+-- http://www.phpmyadmin.net
+--
+-- Host: localhost
+-- Erstellungszeit: 26. Jan 2016 um 10:01
+-- Server Version: 5.6.25
+-- PHP-Version: 5.4.45-1~dotdeb+7.1
+
+SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO";
+SET time_zone = "+00:00";
+
+--
+-- Datenbank: `worktime`
+--
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `location`
+--
+
+CREATE TABLE IF NOT EXISTS `location` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(255) NOT NULL,
+ `tag` varchar(10) NOT NULL,
+ `weeklength` float NOT NULL,
+ `days` text NOT NULL,
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `month`
+--
+
+CREATE TABLE IF NOT EXISTS `month` (
+ `year` int(11) NOT NULL,
+ `month` int(11) NOT NULL,
+ `duration` double NOT NULL,
+ `location` int(11) DEFAULT NULL,
+ UNIQUE KEY `year` (`year`,`month`,`location`),
+ KEY `location` (`location`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `work`
+--
+
+CREATE TABLE IF NOT EXISTS `work` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `date` date NOT NULL,
+ `start` time NOT NULL,
+ `stop` time NOT NULL,
+ `pause` int(11) DEFAULT NULL,
+ `type` enum('ok','free','we','ill','vac','feiertag') NOT NULL,
+ `notice` varchar(200) DEFAULT NULL,
+ `location` int(11) DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ KEY `location` (`location`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- --------------------------------------------------------
+
+--
+-- Tabellenstruktur für Tabelle `_version`
+--
+
+CREATE TABLE IF NOT EXISTS `_version` (
+ `dbver` int(4) NOT NULL,
+ `dbdate` datetime NOT NULL,
+ PRIMARY KEY (`dbver`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+--
+-- Constraints der exportierten Tabellen
+--
+
+--
+-- Constraints der Tabelle `month`
+--
+ALTER TABLE `month`
+ ADD CONSTRAINT `month_ibfk_1` FOREIGN KEY (`location`) REFERENCES `location` (`id`) ON DELETE SET NULL ON UPDATE SET NULL;
+
+--
+-- Constraints der Tabelle `work`
+--
+ALTER TABLE `work`
+ ADD CONSTRAINT `work_ibfk_1` FOREIGN KEY (`location`) REFERENCES `location` (`id`) ON DELETE SET NULL ON UPDATE SET NULL;
+
+--
+-- Daten
+--
+
+INSERT INTO `_version` (`dbver` ,`dbdate`) VALUES ('1', CURRENT_TIMESTAMP);
diff --git a/TimeKeeper/TimeKeeper/Database/TDatabase.cs b/TimeKeeper/TimeKeeper/Database/TDatabase.cs
new file mode 100644
index 0000000..d370285
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Database/TDatabase.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using TimeKeeper.Models.Types;
+
+namespace TimeKeeper.Database {
+ public class TDatabase : DatabaseDriver, IDisposable {
+ private static TDatabase instance;
+
+ private TDatabase() : base(StaticConfig.DbConfig.Engine, StaticConfig.DbConfig.Host, StaticConfig.DbConfig.Port, StaticConfig.DbConfig.Db, StaticConfig.DbConfig.User, StaticConfig.DbConfig.Pass, new DatabaseEngine[] { DatabaseEngine.Mysql}) {
+ // Try and Reconnect
+ try {
+ Connect();
+
+ // Try to get the database version
+ try {
+ if(base.Query("SELECT dbver FROM _version LIMIT 1").Count == 0)
+ throw new Exception();
+ } catch {
+ base.Execute(Utils.GetResourceAsString("TimeKeeper.Database.SQL.MySQL.Install.sql"));
+ }
+ } catch(Exception) {
+ if(Connection != null)
+ Connection.Dispose();
+
+ throw;
+ }
+ }
+
+ public static TDatabase getInstance() {
+ if(instance == null) {
+ instance = new TDatabase();
+ }
+ return instance;
+ }
+
+ ~TDatabase() {
+ if(!IsDisposed)
+ base.Dispose();
+ }
+
+ internal void addWorking(WorkMessage m) {
+ List> dayItems = this.getWorkOnDay(m.time);
+ if(dayItems.Count == 0 && m.working == 1) {
+ this.insertStartWork(m.time, m.jobID);
+ } else if(dayItems.Count > 0) {
+ int started = -1;
+ int job = -1;
+ foreach(Dictionary dayItem in dayItems) {
+ if((TimeSpan)dayItem["stop"] == TimeSpan.Zero) {
+ started = (int)dayItem["id"];
+ job = (int)dayItem["location"];
+ break;
+ }
+ }
+ if(started != -1 && m.working == 0 && m.jobID == job) {
+ this.updateStopWorking(started, m.time);
+ } else if(started == -1 && m.working == 1) {
+ this.insertStartWork(m.time, m.jobID);
+ } else {
+ throw new NotImplementedException();
+ }
+ } else {
+ throw new NotImplementedException();
+ }
+ }
+
+ private void updateStopWorking(Int32 started, DateTime time) {
+ base.Execute("UPDATE `work` SET stop=@P0 WHERE id=@P1",
+ time.ToString("HH:mm:ss"), started.ToString());
+ }
+
+ internal bool insertStartWork(DateTime time, Int32 jobID) {
+ int Rows = base.Execute("INSERT INTO `work` (`date`, `start`, `type`, `location`) VALUES (@P0, @P1, @P2, @P3)",
+ time.ToString("yyyy-MM-dd"), time.ToString("HH:mm:ss"), "ok", jobID.ToString()
+ );
+ return (Rows != 0);
+ }
+
+ internal List> getWorkOnDay(DateTime time) {
+ return base.Query("SELECT * FROM `work` WHERE date=@P0 ORDER BY `start` ASC", time.ToString("yyyy-MM-dd"));
+ }
+
+ ///
+ /// Returns the number of accounts in the database
+ ///
+ ///
+ public int GetNumAccounts() {
+ var Row = base.Query("SELECT COUNT(id) AS count FROM accounts");
+ return Int32.Parse(Row[0]["count"].ToString());
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Exceptions/DbConnectException.cs b/TimeKeeper/TimeKeeper/Exceptions/DbConnectException.cs
new file mode 100644
index 0000000..2f5b102
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Exceptions/DbConnectException.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace TimeKeeper.Exceptions {
+ class DbConnectException : Exception {
+ public DbConnectException(string Message, Exception Inner) : base(Message, Inner) { }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Exceptions/IllegalDataException.cs b/TimeKeeper/TimeKeeper/Exceptions/IllegalDataException.cs
new file mode 100644
index 0000000..a2168f5
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Exceptions/IllegalDataException.cs
@@ -0,0 +1,7 @@
+using System;
+
+namespace TimeKeeper.Exceptions {
+ class IllegalDataException : Exception {
+ public IllegalDataException(string Message, Exception Inner) : base(Message, Inner) { }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Misc/StaticConfig.cs b/TimeKeeper/TimeKeeper/Misc/StaticConfig.cs
new file mode 100644
index 0000000..62cb37d
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Misc/StaticConfig.cs
@@ -0,0 +1,17 @@
+using BlubbFish.Utils;
+using System.Windows.Forms;
+
+namespace TimeKeeper {
+ class StaticConfig {
+ public static class DbConfig {
+ private static InIReader i = InIReader.getInstance("settings.ini");
+ public static string Engine { get { return i.getValue("database", "engine"); } }
+ public static string Host { get { return i.getValue("database", "host"); } }
+ public static int Port { get { return int.Parse(i.getValue("database", "port")); } }
+ public static string Db { get { return i.getValue("database", "db"); } }
+ public static string User { get { return i.getValue("database", "user"); } }
+ public static string Pass { get { return i.getValue("database", "pass"); } }
+ }
+ public static readonly string RootPath = Application.StartupPath;
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Misc/UDPListener.cs b/TimeKeeper/TimeKeeper/Misc/UDPListener.cs
new file mode 100644
index 0000000..050b55f
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Misc/UDPListener.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Text;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using TimeKeeper.Models.Types;
+
+namespace TimeKeeper {
+ class UDPListener {
+ private int m_portToListen = 2003;
+ private volatile bool listening;
+ Thread m_ListeningThread;
+ public event EventHandler NewMessageReceived;
+ UdpClient listener = null;
+ private IPAddress lastAddress;
+ private Int32 tport;
+
+ //constructor
+ public UDPListener(int port, int targetPort) {
+ this.tport = targetPort;
+ this.listening = false;
+ this.m_portToListen = port;
+ this.listener = new UdpClient(this.m_portToListen);
+ }
+
+ public void StartListener() {
+ if(!this.listening) {
+ m_ListeningThread = new Thread(ListenForUDPPackages);
+ m_ListeningThread.IsBackground = true;
+ this.listening = true;
+ m_ListeningThread.Start();
+ }
+ }
+
+ public void StopListener() {
+ this.listening = false;
+ this.listener.Close();
+ }
+
+ public void ListenForUDPPackages() {
+
+ try {
+
+ } catch(SocketException) {
+ //do nothing
+ }
+
+ if(this.listener != null) {
+ IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, m_portToListen);
+
+ try {
+ while(this.listening) {
+ Console.WriteLine("Waiting for UDP broadcast to port " + m_portToListen);
+ byte[] bytes = this.listener.Receive(ref groupEP);
+ this.lastAddress = groupEP.Address;
+ string s = Encoding.ASCII.GetString(bytes);
+ //raise event
+ NewMessageReceived(this, new MyMessageArgs(s));
+ }
+ } catch(Exception e) {
+ Console.WriteLine(e.ToString());
+ } finally {
+ this.listener.Close();
+ Console.WriteLine("Done listening for UDP broadcast");
+ }
+ }
+ }
+
+ internal void WriteLine(String text) {
+ byte[] s = Encoding.ASCII.GetBytes(text);
+ IPEndPoint endpoint = new IPEndPoint(this.lastAddress, this.tport);
+ this.listener.SendAsync(s, s.Length, endpoint);
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Misc/Utils.cs b/TimeKeeper/TimeKeeper/Misc/Utils.cs
new file mode 100644
index 0000000..20a4acb
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Misc/Utils.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TimeKeeper {
+ class Utils {
+ public static string GetResourceAsString(string ResName) {
+ string Res = "";
+ using(Stream ResourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(ResName)) {
+ using(StreamReader Reader = new StreamReader(ResourceStream)) {
+ Res = Reader.ReadToEnd();
+ }
+ }
+ return Res;
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Models/MDatabase.cs b/TimeKeeper/TimeKeeper/Models/MDatabase.cs
new file mode 100644
index 0000000..149ab65
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Models/MDatabase.cs
@@ -0,0 +1,31 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using TimeKeeper.Database;
+using TimeKeeper.Models.Types;
+
+namespace TimeKeeper.Models {
+ class Database : OwnModel {
+ private TDatabase database;
+
+ public Queue Messages { get; internal set; }
+
+ protected override void init() {
+ this.database = TDatabase.getInstance();
+ }
+
+ private Database() {
+ this.init();
+ }
+
+ internal void checkinMessages() {
+ while(this.Messages.Count > 0) {
+ WorkMessage m = this.Messages.Dequeue();
+ this.database.addWorking(m);
+ }
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Models/MTray.cs b/TimeKeeper/TimeKeeper/Models/MTray.cs
new file mode 100644
index 0000000..c27cc60
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Models/MTray.cs
@@ -0,0 +1,137 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Threading;
+using TimeKeeper.Exceptions;
+using TimeKeeper.Models.Types;
+
+namespace TimeKeeper.Models {
+ class Tray : OwnModel {
+ private Boolean isConnectedValue = false;
+ private TimeSpan OffsetTimeValue = new TimeSpan();
+ private UDPListener network;
+ private Thread setTimeThread;
+ private InIReader settingsfile;
+ private FileLogger sLogger;
+ private Queue MessagesValue = new Queue();
+ private Database DatabaseModel;
+ private Boolean initComplete = false;
+
+ private Tray() {
+ this.sLogger = FileLogger.getInstance("network.log", false);
+ this.init();
+ }
+
+ public Boolean isConnected {
+ get { return this.isConnectedValue; }
+ set { this.isConnectedValue = value; this.update(); }
+ }
+
+ public TimeSpan OffsetTime {
+ get { return this.OffsetTimeValue; }
+ set { this.OffsetTimeValue = value; this.update(); }
+ }
+
+ public Queue Messages {
+ get { return this.MessagesValue; }
+ }
+
+ public void MessagesPush(WorkMessage m) {
+ this.MessagesValue.Enqueue(m);
+ this.update();
+ this.DatabaseModel.Messages = this.Messages;
+ this.DatabaseModel.checkinMessages();
+ }
+
+ override protected void init() {
+ this.settingsfile = InIReader.getInstance("settings.ini");
+ this.network = new UDPListener(Int32.Parse(this.settingsfile.getValue("general", "port")), Int32.Parse(this.settingsfile.getValue("general", "arduinoport")));
+ this.network.NewMessageReceived += DataReceivedHandler;
+ this.network.StartListener();
+ this.setTimeThread = new Thread(timeRunner);
+ this.setTimeThread.Start();
+ this.DatabaseModel = Database.Instance;
+ }
+
+ internal void Dispose() {
+ this.setTimeThread.Abort();
+ this.network.NewMessageReceived -= DataReceivedHandler;
+ this.network.StopListener();
+ }
+
+ private void timeRunner() {
+ while(!this.initComplete) {
+ Thread.Sleep(100);
+ }
+ while(true) {
+ DateTime n = DateTime.UtcNow;
+ this.DataSendHandler("time=" + ((int)((n - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds)).ToString());
+ Thread.Sleep(1000 * 60 * 5);
+ }
+ }
+
+ private void DataReceivedHandler(Object sender, MyMessageArgs s) {
+ sLogger.setLine("<-: " + s.data, DateTime.Now);
+ this.parseSerial(s.data);
+ }
+
+ [MethodImpl(MethodImplOptions.Synchronized)]
+ private void DataSendHandler(String v) {
+ sLogger.setLine("->: " + v, DateTime.Now);
+ this.network.WriteLine(v);
+ }
+
+ private void parseSerial(String s) {
+ if(s == "requestKeep=1") {
+ this.DataSendHandler("keep=1");
+ } else if(s == "Init...." ||
+ s == "Init loading!" ||
+ s == "Start Network!" ||
+ s == "DHCP Request" ||
+ s == "Ethernet Started! IP: 129.26.160.107.") {
+ //Ignore that Stuff
+ } else if(s == "Init finished!") {
+ this.initComplete = true;
+ } else if((s.Length > 4 && s.Substring(0, 4) == "d->:") || (s.Length > 4 && s.Substring(0, 4) == "i<-:")) {
+ //Ignore that Stuff also....
+ } else if(s.Length > 2 && s.Substring(0, 2) == "t=") {
+ this.setOffset(s.Split('=')[1]);
+ } else if(s.Length > 4 && s.Substring(0, 4) == "tag=") {
+ this.parseTag(s);
+ } else {
+ throw new NotImplementedException();
+ }
+ }
+
+ private void parseTag(String s) {
+ string[] parts = s.Split(';');
+ long userID = 0;
+ DateTime time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ int jobID = 0;
+ int working = 0;
+ foreach(String part in parts) {
+ string[] t = part.Split('=');
+ if(t[0] == "tag") {
+ userID = long.Parse(t[1]);
+ } else if(t[0] == "time") {
+ time = time.AddSeconds(int.Parse(t[1])).ToLocalTime();
+ } else if(t[0] == "job") {
+ jobID = int.Parse(t[1]);
+ if(jobID == -1) {
+ throw new IllegalDataException("JobID ist -1", null);
+ }
+ } else if(t[0] == "online") {
+ working = int.Parse(t[1]);
+ }
+ }
+ this.MessagesPush(new WorkMessage(userID, time, jobID, working));
+ }
+
+ private void setOffset(String v) {
+ DateTime ctime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
+ ctime = ctime.AddSeconds(int.Parse(v)).ToLocalTime();
+ this.OffsetTime = ctime - DateTime.Now;
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Models/MWindow.cs b/TimeKeeper/TimeKeeper/Models/MWindow.cs
new file mode 100644
index 0000000..d56ac60
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Models/MWindow.cs
@@ -0,0 +1,19 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TimeKeeper.Models {
+ class Window : OwnModel {
+
+ private Window() {
+ this.init();
+ }
+
+ override protected void init() {
+
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Models/Types/MyMessageArgs.cs b/TimeKeeper/TimeKeeper/Models/Types/MyMessageArgs.cs
new file mode 100644
index 0000000..3f68e8d
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Models/Types/MyMessageArgs.cs
@@ -0,0 +1,11 @@
+using System;
+
+namespace TimeKeeper.Models.Types {
+ public class MyMessageArgs : EventArgs {
+ public string data { get; set; }
+
+ public MyMessageArgs(string newData) {
+ data = newData;
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Models/Types/WorkMessage.cs b/TimeKeeper/TimeKeeper/Models/Types/WorkMessage.cs
new file mode 100644
index 0000000..6df46f6
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Models/Types/WorkMessage.cs
@@ -0,0 +1,17 @@
+using System;
+
+namespace TimeKeeper.Models.Types {
+ class WorkMessage {
+ public Int32 jobID;
+ public DateTime time;
+ public Int64 userID;
+ public Int32 working;
+
+ public WorkMessage(Int64 userID, DateTime time, Int32 jobID, Int32 working) {
+ this.userID = userID;
+ this.time = time;
+ this.jobID = jobID;
+ this.working = working;
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Program.cs b/TimeKeeper/TimeKeeper/Program.cs
new file mode 100644
index 0000000..e43401a
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Program.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Windows.Forms;
+using BlubbFish.Utils;
+
+namespace TimeKeeper {
+ class Program {
+ static void Main(string[] args) {
+ FileLogger.setLogDir("logs");
+ try {
+ Controller.Tray t = new Controller.Tray();
+ t.execute();
+ Application.Run();
+ } catch(Exception e) {
+ if(e.InnerException != null) {
+ e = e.InnerException;
+ }
+ MessageBox.Show("Fehler: " + e.Message + "\nStack: " + e.StackTrace, "Exception: " + e.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Properties/AssemblyInfo.cs b/TimeKeeper/TimeKeeper/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..5f9a202
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Properties/AssemblyInfo.cs
@@ -0,0 +1,38 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Resources;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("TimeKeeper")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("TimeKeeper")]
+[assembly: AssemblyCopyright("Copyright BlubbFish © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("7df6ab3d-639f-4549-a770-10ba3540a26b")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: NeutralResourcesLanguageAttribute("de-DE")]
diff --git a/TimeKeeper/TimeKeeper/Properties/Resources.Designer.cs b/TimeKeeper/TimeKeeper/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..5d3e41a
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Properties/Resources.Designer.cs
@@ -0,0 +1,103 @@
+//------------------------------------------------------------------------------
+//
+// Dieser Code wurde von einem Tool generiert.
+// Laufzeitversion:4.0.30319.34209
+//
+// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
+// der Code erneut generiert wird.
+//
+//------------------------------------------------------------------------------
+
+namespace TimeKeeper.Properties {
+ using System;
+
+
+ ///
+ /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
+ ///
+ // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
+ // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
+ // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
+ // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ ///
+ /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("TimeKeeper.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
+ /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
+ ///
+ internal static System.Drawing.Icon IconMain {
+ get {
+ object obj = ResourceManager.GetObject("IconMain", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
+ ///
+ internal static System.Drawing.Bitmap MenuImagesQuit {
+ get {
+ object obj = ResourceManager.GetObject("MenuImagesQuit", resourceCulture);
+ return ((System.Drawing.Bitmap)(obj));
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
+ ///
+ internal static System.Drawing.Icon TrayIconConnected {
+ get {
+ object obj = ResourceManager.GetObject("TrayIconConnected", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
+ ///
+ internal static System.Drawing.Icon TrayIconDisconnected {
+ get {
+ object obj = ResourceManager.GetObject("TrayIconDisconnected", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/Properties/Resources.resx b/TimeKeeper/TimeKeeper/Properties/Resources.resx
new file mode 100644
index 0000000..5f9c014
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/Properties/Resources.resx
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+ ..\Resources\Icons\main.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Icons\door_open.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Icons\main_con.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\Resources\Icons\main_dis.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
\ No newline at end of file
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/connect.png b/TimeKeeper/TimeKeeper/Resources/Icons/connect.png
new file mode 100644
index 0000000..6c78bbd
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/connect.png differ
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/disconnect.png b/TimeKeeper/TimeKeeper/Resources/Icons/disconnect.png
new file mode 100644
index 0000000..4ffb7fc
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/disconnect.png differ
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/door_open.png b/TimeKeeper/TimeKeeper/Resources/Icons/door_open.png
new file mode 100644
index 0000000..64bab57
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/door_open.png differ
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/main.ico b/TimeKeeper/TimeKeeper/Resources/Icons/main.ico
new file mode 100644
index 0000000..d87a506
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/main.ico differ
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/main_con.ico b/TimeKeeper/TimeKeeper/Resources/Icons/main_con.ico
new file mode 100644
index 0000000..35adfe6
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/main_con.ico differ
diff --git a/TimeKeeper/TimeKeeper/Resources/Icons/main_dis.ico b/TimeKeeper/TimeKeeper/Resources/Icons/main_dis.ico
new file mode 100644
index 0000000..0eebf30
Binary files /dev/null and b/TimeKeeper/TimeKeeper/Resources/Icons/main_dis.ico differ
diff --git a/TimeKeeper/TimeKeeper/TimeKeeper.csproj b/TimeKeeper/TimeKeeper/TimeKeeper.csproj
new file mode 100644
index 0000000..c79d241
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/TimeKeeper.csproj
@@ -0,0 +1,123 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {25F58397-71CB-4298-979E-BAACE80C61CB}
+ WinExe
+ Properties
+ TimeKeeper
+ TimeKeeper
+ v4.5
+ 512
+
+
+ x64
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ x64
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ TimeKeeper.Program
+
+
+ Resources\Icons\main.ico
+
+
+
+ ..\lib\MySql.Data.dll
+
+
+
+
+ False
+ ..\lib\System.Data.SQLite.dll
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+ Form
+
+
+ ViewWindowForm.cs
+
+
+
+
+
+
+ {fac8ce64-bf13-4ece-8097-aeb5dd060098}
+ Utils
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+ PreserveNewest
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TimeKeeper/TimeKeeper/View/VTray.cs b/TimeKeeper/TimeKeeper/View/VTray.cs
new file mode 100644
index 0000000..2d5e724
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/View/VTray.cs
@@ -0,0 +1,87 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using TimeKeeper.Properties;
+using System.Drawing;
+using TimeKeeper.Models;
+
+namespace TimeKeeper.View {
+ class Tray : OwnView {
+ public Models.Tray Model { get; private set; }
+
+ private NotifyIcon trayi;
+ private Icon[] trayIcons = { new Icon(Resources.TrayIconConnected, 40, 40), new Icon(Resources.TrayIconDisconnected, 40, 40) };
+ private Boolean offsetTimeFail;
+
+ public Tray() {
+ this.init();
+ this.Model = Models.Tray.Instance;
+ this.Model.setObserver(this);
+ }
+
+ public override void update() {
+ this.trayi.ContextMenuStrip = this.genMenu();
+ this.trayi.Icon = (this.Model.isConnected) ? this.trayIcons[0] : this.trayIcons[1];
+ if(this.Model.Messages.Count > 0) {
+ Models.Types.WorkMessage m = this.Model.Messages.Peek();
+ string text = (m.working==1)?"Angefangen zu arbeiten ":"Aufgehört zu arbeiten ";
+ text += "am " + m.time.ToShortDateString() + " " + m.time.ToLongTimeString() + " ";
+ text += "in Job " + m.jobID.ToString();
+ this.showBallonTooltip(text, ToolTipIcon.Info);
+ } else if(Math.Abs(this.Model.OffsetTime.TotalSeconds) >= 2) {
+ this.showBallonTooltip("Achtung Abweichung von der Zeit: " + this.Model.OffsetTime.TotalSeconds, ToolTipIcon.Warning);
+ this.offsetTimeFail = true;
+ } else if(Math.Abs(this.Model.OffsetTime.TotalSeconds) < 2 && this.offsetTimeFail) {
+ this.showBallonTooltip("Zeitabweichung ok: " + this.Model.OffsetTime.TotalSeconds, ToolTipIcon.Info);
+ this.offsetTimeFail = false;
+ }
+ }
+
+ override protected void init() {
+ this.trayi = new NotifyIcon();
+ this.trayi.Visible = true;
+ this.trayi.Icon = this.trayIcons[1];
+ this.trayi.Text = "TimeKeeper";
+ this.trayi.DoubleClick += Controller.Tray.Click_Tray;
+ }
+
+ override public void Dispose() {
+ this.trayi.Visible = false;
+ this.Model.Dispose();
+ Application.ExitThread();
+ }
+
+ private ContextMenuStrip genMenu() {
+ ContextMenuStrip menu = new ContextMenuStrip();
+ ToolStripMenuItem mo = new ToolStripMenuItem("Öffnen");
+ mo.Image = Resources.MenuImagesQuit;
+ mo.Click += Controller.Tray.Click_Open;
+ mo.Name = "Open";
+ menu.Items.Add(mo);
+
+ menu.Items.Add(new ToolStripSeparator());
+
+ ToolStripMenuItem mq = new ToolStripMenuItem("Beenden");
+ mq.Image = Resources.MenuImagesQuit;
+ mq.Click += Controller.Tray.Click_Quit;
+ mq.Name = "Quit";
+ menu.Items.Add(mq);
+ return menu;
+ }
+
+ private void showBallonTooltip(string text, ToolTipIcon toolTipIcon, string title = "TimeKeeper Tray") {
+ this.trayi.BalloonTipIcon = toolTipIcon;
+ this.trayi.BalloonTipText = text;
+ this.trayi.BalloonTipTitle = title;
+ this.trayi.ShowBalloonTip(100);
+ }
+
+ internal void showError(string text) {
+ this.showBallonTooltip(text, ToolTipIcon.Error);
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/View/VWindow.cs b/TimeKeeper/TimeKeeper/View/VWindow.cs
new file mode 100644
index 0000000..10f7ad0
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/View/VWindow.cs
@@ -0,0 +1,35 @@
+using BlubbFish.Utils;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TimeKeeper.View {
+ class Window : OwnView {
+ private ViewWindowForm form;
+ public Window() {
+ this.form = new ViewWindowForm();
+ this.init();
+ this.Model.setObserver(this);
+ }
+
+ public override void update() {
+ this.form.UpdateForm();
+ }
+
+ protected override void init() {
+ this.Model = Models.Window.Instance;
+ this.form.SetModel(this.Model);
+ this.form.Show();
+ }
+
+ public override void Dispose() {
+ this.form.BeginInvoke((Action)(() => {
+ this.form.Dispose();
+ }));
+ }
+
+ public Models.Window Model { get; private set; }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/View/ViewWindowForm.Designer.cs b/TimeKeeper/TimeKeeper/View/ViewWindowForm.Designer.cs
new file mode 100644
index 0000000..9ffc2e7
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/View/ViewWindowForm.Designer.cs
@@ -0,0 +1,33 @@
+namespace TimeKeeper.View {
+ partial class ViewWindowForm {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if(disposing && (components != null)) {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent() {
+ this.components = new System.ComponentModel.Container();
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Text = "ViewWindowForm";
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/TimeKeeper/TimeKeeper/View/ViewWindowForm.cs b/TimeKeeper/TimeKeeper/View/ViewWindowForm.cs
new file mode 100644
index 0000000..9addef3
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/View/ViewWindowForm.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace TimeKeeper.View {
+ public partial class ViewWindowForm : Form {
+ private Models.Window model;
+
+ public ViewWindowForm() {
+ InitializeComponent();
+ this.FormClosed += Controller.Window.FormClosed;
+ this.Icon = TimeKeeper.Properties.Resources.IconMain;
+ }
+
+ public void UpdateForm() {
+ this.BeginInvoke((Action)(() => {
+
+ }));
+ }
+
+ internal void SetModel(Models.Window window) {
+ this.model = window;
+ }
+ }
+}
diff --git a/TimeKeeper/TimeKeeper/bin/Release/TimeKeeper.exe b/TimeKeeper/TimeKeeper/bin/Release/TimeKeeper.exe
new file mode 100644
index 0000000..00c5717
Binary files /dev/null and b/TimeKeeper/TimeKeeper/bin/Release/TimeKeeper.exe differ
diff --git a/TimeKeeper/TimeKeeper/bin/Release/Utils.dll b/TimeKeeper/TimeKeeper/bin/Release/Utils.dll
new file mode 100644
index 0000000..0dd4d12
Binary files /dev/null and b/TimeKeeper/TimeKeeper/bin/Release/Utils.dll differ
diff --git a/TimeKeeper/TimeKeeper/bin/Release/settings.ini b/TimeKeeper/TimeKeeper/bin/Release/settings.ini
new file mode 100644
index 0000000..d03527a
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/bin/Release/settings.ini
@@ -0,0 +1,2 @@
+[general]
+comport=COM4
\ No newline at end of file
diff --git a/TimeKeeper/TimeKeeper/settings.ini b/TimeKeeper/TimeKeeper/settings.ini
new file mode 100644
index 0000000..b5bad6c
--- /dev/null
+++ b/TimeKeeper/TimeKeeper/settings.ini
@@ -0,0 +1,11 @@
+[general]
+port=28654
+arduinoport=25987
+
+[database]
+engine=Mysql
+host=localhost
+port=3306
+db=worktime
+user=root
+pass=mafia
\ No newline at end of file
diff --git a/TimeKeeper/lib/MySql.Data.dll b/TimeKeeper/lib/MySql.Data.dll
new file mode 100644
index 0000000..fd3c20a
Binary files /dev/null and b/TimeKeeper/lib/MySql.Data.dll differ
diff --git a/TimeKeeper/lib/System.Data.SQLite.dll b/TimeKeeper/lib/System.Data.SQLite.dll
new file mode 100644
index 0000000..ad11eca
Binary files /dev/null and b/TimeKeeper/lib/System.Data.SQLite.dll differ
diff --git a/Utils/Utils.sln b/Utils/Utils.sln
new file mode 100644
index 0000000..012783f
--- /dev/null
+++ b/Utils/Utils.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Utils", "Utils\Utils.csproj", "{FAC8CE64-BF13-4ECE-8097-AEB5DD060098}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {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
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/Utils/Utils/CmdArgs.cs b/Utils/Utils/CmdArgs.cs
new file mode 100644
index 0000000..ddadc6b
--- /dev/null
+++ b/Utils/Utils/CmdArgs.cs
@@ -0,0 +1,186 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace BlubbFish.Utils
+{
+ public class CmdArgs
+ {
+ public enum ArgLength
+ {
+ Single,
+ Touple
+ }
+ #region Classes
+ public struct VaildArguments
+ {
+ public VaildArguments(ArgLength length, Boolean required)
+ {
+ this.Required = required;
+ this.Length = length;
+ }
+ public VaildArguments(ArgLength length)
+ {
+ this.Required = false;
+ this.Length = length;
+ }
+
+ public ArgLength Length { get; private set; }
+ public Boolean Required { get; private set; }
+ }
+ private struct ArgTouple
+ {
+ public ArgTouple(String type, String data)
+ {
+ this.Type = type;
+ this.Data = data;
+ }
+ public ArgTouple(String type)
+ {
+ this.Type = type;
+ this.Data = "";
+ }
+ public String Type { get; private set; }
+ public String Data { get; private set; }
+
+ internal void SetData(String data)
+ {
+ if (data != "") {
+ this.Data = data;
+ }
+ }
+ }
+ #endregion
+ private String[] args;
+ private List argList;
+ private Dictionary argsPosible = new Dictionary();
+ private static CmdArgs instances = null;
+ private Boolean isSetArguments = false;
+
+ private CmdArgs()
+ {
+ }
+
+ ///
+ /// Gibt eine Instanz der Klasse zurück
+ ///
+ /// Klasse
+ public static CmdArgs Instance
+ {
+ get {
+ if (instances == null) {
+ instances = new CmdArgs();
+ }
+ return instances;
+ }
+ }
+
+ ///
+ /// Übernimmt die Argumente für die Klasse
+ ///
+ /// Mögliche Komandozeilenargumente
+ /// Tatsächliche Komandozeilenargumente
+ public void SetArguments(Dictionary arguments, String[] args)
+ {
+ this.args = args;
+ if (!this.isSetArguments) {
+ this.isSetArguments = true;
+ this.argsPosible = arguments;
+ this.Init();
+ }
+ }
+
+ private void Init()
+ {
+ this.argList = new List();
+ for (Int32 i = 0; i < this.args.Length; i++) {
+ if (this.argsPosible.Keys.Contains(this.args[i])) {
+ ArgTouple arg = new ArgTouple(this.args[i]);
+ if (this.argsPosible[this.args[i]].Length == ArgLength.Touple) {
+ if (this.args.Length > i + 1) {
+ arg.SetData(this.args[++i]);
+ } else {
+ throw new ArgumentException();
+ }
+ }
+ this.argList.Add(arg);
+ }
+ }
+ }
+
+ ///
+ /// Menge der angegebenen Komandozeilen-Argumente
+ ///
+ /// Menge
+ public Int32 GetArgsLength()
+ {
+ return this.argList.Count;
+ }
+
+ ///
+ /// Gibt zurück ob ein Argument angegeben wurde
+ ///
+ /// Name des Arguments
+ /// true wenn angegeben
+ public Boolean HasArgumentType(String name)
+ {
+ foreach (ArgTouple t in this.argList) {
+ if (t.Type == name) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ ///
+ /// Gibt den Inhalt des angegeben Arguments zurück, nur bei zweiteiligen Argumenten möglich
+ ///
+ /// Name des Arguments
+ /// Inhalt des Arguments oder ArgumentNullException
+ public String GetArgumentData(String name)
+ {
+ foreach (ArgTouple t in this.argList) {
+ if (t.Type == name && t.Data != null) {
+ return t.Data;
+ } else {
+ throw new ArgumentNullException();
+ }
+ }
+ return null;
+ }
+
+ public Boolean HasAllRequiredArguments()
+ {
+ foreach (KeyValuePair item in this.argsPosible) {
+ if (item.Value.Required && !this.HasArgumentType(item.Key)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public String GetUsageList(String name)
+ {
+ String ret = "Usage: " + name + " Parameter\nParameter:\n";
+ String req = "";
+ String opt = "";
+ foreach (KeyValuePair item in this.argsPosible) {
+ if (item.Value.Required) {
+ req += item.Key + " " + ((item.Value.Length == ArgLength.Touple) ? " [data]\n" : "\n");
+ }
+ }
+ if (req != "") {
+ ret += "Benötigte Parameter:\n" + req;
+ }
+ foreach (KeyValuePair item in this.argsPosible) {
+ if (!item.Value.Required) {
+ opt += item.Key + " " + ((item.Value.Length == ArgLength.Touple) ? " [data]\n" : "\n");
+ }
+ }
+ if (opt != "") {
+ ret += "Optionale Parameter:\n" + opt;
+ }
+ return ret;
+ }
+ }
+}
diff --git a/Utils/Utils/EventArgsHelper.cs b/Utils/Utils/EventArgsHelper.cs
new file mode 100644
index 0000000..b87fd6f
--- /dev/null
+++ b/Utils/Utils/EventArgsHelper.cs
@@ -0,0 +1,34 @@
+using System;
+
+namespace BlubbFish.Utils {
+ public class UpdaterEventArgs : EventArgs {
+ public UpdaterEventArgs(Boolean hasUpdates, String message) {
+ this.HasUpdates = hasUpdates;
+ this.Message = message;
+ }
+ public String Message { get; private set; }
+ public Boolean HasUpdates { get; private set; }
+ }
+
+ public class UpdaterFailEventArgs : EventArgs {
+ public UpdaterFailEventArgs(Exception e) {
+ this.Except = e;
+ }
+
+ public Exception Except { get; private set; }
+ }
+
+ public class LogEventArgs : EventArgs {
+ public LogEventArgs(String location, String message, OwnObject.LogLevel level, DateTime date) {
+ this.Location = location;
+ this.Message = message;
+ this.Level = level;
+ this.Date = date;
+ }
+
+ public String Location { get; private set; }
+ public String Message { get; private set; }
+ public OwnObject.LogLevel Level { get; private set; }
+ public DateTime Date { get; private set; }
+ }
+}
diff --git a/Utils/Utils/FileLogger.cs b/Utils/Utils/FileLogger.cs
new file mode 100644
index 0000000..9dd397f
--- /dev/null
+++ b/Utils/Utils/FileLogger.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.IO;
+using System.Reflection;
+
+namespace BlubbFish.Utils
+{
+ public class FileLogger
+ {
+ private static Dictionary instances = new Dictionary();
+ private static String logDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar;
+ private StreamWriter file;
+ private FileLogger(String filename, Boolean append)
+ {
+ filename = logDir + filename;
+ if (!File.Exists(filename)) {
+ String folder = Path.GetDirectoryName(Path.GetFullPath(filename));
+ if (!Directory.Exists(folder)) {
+ Directory.CreateDirectory(folder);
+ }
+ }
+ this.file = new StreamWriter(filename, append, Encoding.UTF8) {
+ AutoFlush = true
+ };
+ }
+ public static FileLogger GetInstance(String filename, Boolean append)
+ {
+ if (!instances.Keys.Contains(filename)) {
+ instances.Add(filename, new FileLogger(filename, append));
+ }
+ return instances[filename];
+ }
+
+ public static void SetLogDir(String v)
+ {
+ v = v.Replace("..", "");
+ v = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + v;
+ if (Directory.Exists(v)) {
+ logDir = v;
+ } else {
+ Directory.CreateDirectory(v);
+ logDir = v;
+ }
+ if (logDir.Substring(logDir.Length - 1) != Path.DirectorySeparatorChar.ToString()) {
+ logDir = logDir + Path.DirectorySeparatorChar;
+ }
+ }
+
+ public void SetArray(String[] text)
+ {
+ this.file.Write(String.Join(this.file.NewLine, text) + this.file.NewLine);
+ this.file.Flush();
+ }
+
+ public void SetLine(String text)
+ {
+ this.file.WriteLine(text);
+ this.file.Flush();
+ }
+ public void SetLine(String text, DateTime d)
+ {
+ this.SetLine(d.ToString("[yyyy-MM-dd HH:mm:ss.ffff] ") + text);
+ }
+ }
+}
diff --git a/Utils/Utils/FileMutex.cs b/Utils/Utils/FileMutex.cs
new file mode 100644
index 0000000..567b753
--- /dev/null
+++ b/Utils/Utils/FileMutex.cs
@@ -0,0 +1,71 @@
+using System;
+using System.IO;
+using System.Security.Cryptography;
+using System.Text;
+
+namespace BlubbFish.Utils
+{
+ public class FileMutex : IDisposable
+ {
+ private static FileMutex instance;
+ private String filename;
+ private StreamWriter file;
+ private FileMutex() { }
+
+ public static FileMutex Instance
+ {
+ get {
+ if (instance == null) {
+ instance = new FileMutex();
+ }
+ return instance;
+ }
+ }
+
+ public void SetName(String name)
+ {
+ String path = AppDomain.CurrentDomain.BaseDirectory;
+ this.filename = path + String.Join(String.Empty, Array.ConvertAll(new SHA512Managed().ComputeHash(Encoding.UTF8.GetBytes(name)), b => b.ToString("X2"))) + ".lock.txt";
+ }
+
+ public Boolean Create()
+ {
+ if (File.Exists(this.filename)) {
+ return false;
+ }
+
+ this.file = new StreamWriter(this.filename);
+ InitFile();
+ return File.Exists(this.filename) && this.file != null;
+ }
+
+ private void InitFile()
+ {
+ this.file.Write("Created: " + DateTime.Now.ToUniversalTime() + "\n");
+ this.file.Flush();
+ }
+
+ public Boolean Delete()
+ {
+ if(this.file != null) {
+ this.file.Close();
+ }
+
+ File.Delete(this.filename);
+ return !File.Exists(this.filename);
+ }
+
+ protected virtual void Dispose(Boolean disposing) {
+ if (disposing) {
+ if(this.file != null) {
+ this.file.Close();
+ }
+ }
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/Utils/Utils/InIReader.cs b/Utils/Utils/InIReader.cs
new file mode 100644
index 0000000..c87b449
--- /dev/null
+++ b/Utils/Utils/InIReader.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+using System.Threading.Tasks;
+
+namespace BlubbFish.Utils
+{
+ public class InIReader : IDisposable
+ {
+ private Dictionary> inifile;
+ private FileSystemWatcher k = new FileSystemWatcher(Directory.GetCurrentDirectory(), "*.ini");
+ private String filename;
+
+ private static Dictionary instances = new Dictionary();
+
+ private InIReader(String filename)
+ {
+ this.filename = filename;
+ this.k.Changed += new FileSystemEventHandler(this.ReadAgain);
+ LoadFile();
+ }
+
+ public static InIReader GetInstance(String filename)
+ {
+ if (!instances.Keys.Contains(filename)) {
+ instances.Add(filename, new InIReader(filename));
+ }
+ return instances[filename];
+ }
+
+ private void ReadAgain(Object sender, EventArgs e)
+ {
+ this.LoadFile();
+ }
+
+ private void LoadFile()
+ {
+ this.inifile = new Dictionary>();
+ StreamReader file = new StreamReader(this.filename);
+ List buf = new List();
+ String fline = "";
+ while (fline != null) {
+ fline = file.ReadLine();
+ if (fline != null && fline.Length > 0 && fline.Substring(0, 1) != ";") {
+ buf.Add(fline);
+ }
+ }
+ file.Close();
+ Dictionary sub = new Dictionary();
+ String cap = "";
+ foreach (String line in buf) {
+ Match match = Regex.Match(line, @"^\[[a-zA-ZäöüÄÖÜ0-9\-_ ]+\]\w*$", RegexOptions.IgnoreCase);
+ if (match.Success) {
+ if (sub.Count != 0 && cap != "") {
+ this.inifile.Add(cap, sub);
+ }
+ cap = line;
+ sub = new Dictionary();
+ } else {
+ if (line != "" && cap != "") {
+ String key = line.Substring(0, line.IndexOf('='));
+ String value = line.Substring(line.IndexOf('=') + 1);
+ sub.Add(key, value);
+ }
+ }
+ }
+ if (sub.Count != 0 && cap != "") {
+ this.inifile.Add(cap, sub);
+ }
+ }
+
+ public List GetSections(Boolean withBrackets = true)
+ {
+ if(withBrackets) {
+ return this.inifile.Keys.ToList();
+ } else {
+ List ret = new List();
+ foreach (String item in this.inifile.Keys) {
+ ret.Add(item.Substring(1, item.Length - 2));
+ }
+ return ret;
+ }
+ }
+
+ public Dictionary GetSection(String section) {
+ if(this.inifile.Keys.Contains(section)) {
+ return this.inifile[section];
+ }
+ if(this.inifile.Keys.Contains("["+section+"]")) {
+ return this.inifile["[" + section + "]"];
+ }
+ return new Dictionary();
+ }
+
+ public String GetValue(String section, String key)
+ {
+ if (!section.StartsWith("[")) {
+ section = "[" + section + "]";
+ }
+ if (this.inifile.Keys.Contains(section)) {
+ if (this.inifile[section].Keys.Contains(key)) {
+ return this.inifile[section][key];
+ }
+ }
+ return null;
+ }
+
+
+ public void SetValue(String section, String key, String value)
+ {
+ if (!section.StartsWith("[")) {
+ section = "[" + section + "]";
+ }
+ if (this.inifile.Keys.Contains(section)) {
+ if (this.inifile[section].Keys.Contains(key)) {
+ this.inifile[section][key] = value;
+ } else {
+ this.inifile[section].Add(key, value);
+ }
+ } else {
+ Dictionary sub = new Dictionary {
+ { key, value }
+ };
+ this.inifile.Add(section, sub);
+ }
+ this.Changed();
+ }
+
+ private void Changed()
+ {
+ this.k.Changed -= null;
+ SaveSettings();
+ LoadFile();
+ this.k.Changed += new FileSystemEventHandler(this.ReadAgain);
+ }
+
+ private void SaveSettings()
+ {
+ StreamWriter file = new StreamWriter(this.filename);
+ file.BaseStream.SetLength(0);
+ file.BaseStream.Flush();
+ file.BaseStream.Seek(0, SeekOrigin.Begin);
+ foreach (KeyValuePair> cap in this.inifile) {
+ file.WriteLine(cap.Key);
+ foreach (KeyValuePair sub in cap.Value) {
+ file.WriteLine(sub.Key + "=" + sub.Value);
+ }
+ file.WriteLine();
+ }
+ file.Flush();
+ file.Close();
+ }
+
+ ///
+ /// Fügt eine neue Sektion in der Ini-Datei ein.
+ ///
+ /// Sektionsname
+ /// true if added, false if error
+ public Boolean AddSection(String name)
+ {
+ if (!name.StartsWith("[")) {
+ name = "[" + name + "]";
+ }
+ if (this.inifile.Keys.Contains(name)) {
+ return false;
+ }
+ this.inifile.Add(name, new Dictionary());
+ this.Changed();
+ return true;
+ }
+
+ ///
+ /// Löscht eine Sektion inklusive Unterpunkte aus der Ini-Datei.
+ ///
+ /// Sektionsname
+ /// true if removed, false if error
+ public Boolean RemoveSection(String name)
+ {
+ if (!name.StartsWith("[")) {
+ name = "[" + name + "]";
+ }
+ if (!this.inifile.Keys.Contains(name)) {
+ return false;
+ }
+ this.inifile.Remove(name);
+ this.Changed();
+ return false;
+ }
+ protected virtual void Dispose(Boolean disposing) {
+ if (disposing) {
+ this.k.Dispose();
+ }
+ }
+
+ public void Dispose() {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+ }
+}
diff --git a/Utils/Utils/OwnController.cs b/Utils/Utils/OwnController.cs
new file mode 100644
index 0000000..385827e
--- /dev/null
+++ b/Utils/Utils/OwnController.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+
+namespace BlubbFish.Utils
+{
+ public abstract class OwnController
+ {
+ ///
+ /// Führt den Controller aus.
+ ///
+ public void Execute()
+ {
+ this.Init();
+ }
+ abstract protected void Init();
+ abstract public void Dispose();
+ }
+}
diff --git a/Utils/Utils/OwnModel.cs b/Utils/Utils/OwnModel.cs
new file mode 100644
index 0000000..7d566fe
--- /dev/null
+++ b/Utils/Utils/OwnModel.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BlubbFish.Utils
+{
+ public abstract class OwnModel where T : class
+ {
+ private static readonly Lazy _instance = new Lazy(() => CreateInstanceOfT());
+ private List observer = new List();
+ public static T Instance
+ {
+ get {
+ return _instance.Value;
+ }
+ }
+ private static T CreateInstanceOfT()
+ {
+ return Activator.CreateInstance(typeof(T), true) as T;
+ }
+
+ public void SetObserver(OwnView view)
+ {
+ this.observer.Add(view);
+ view.Update();
+ }
+
+ public void RemoveObserver(OwnView view) {
+ this.observer.Remove(view);
+ }
+ protected void Update()
+ {
+ this.observer.ForEach(delegate (OwnView view) { view.Update(); });
+ }
+ abstract protected void Init();
+ }
+}
diff --git a/Utils/Utils/OwnObject.cs b/Utils/Utils/OwnObject.cs
new file mode 100644
index 0000000..7a6c661
--- /dev/null
+++ b/Utils/Utils/OwnObject.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+
+namespace BlubbFish.Utils
+{
+ abstract public class OwnObject
+ {
+ public struct LogObject {
+ public LogObject(DateTime date, String location, String message, LogLevel level) {
+ this.Date = date;
+ this.Location = location;
+ this.Message = message;
+ this.Level = level;
+ }
+
+ public DateTime Date { get; set; }
+ public String Location { get; set; }
+ public String Message { get; set; }
+ public LogLevel Level { get; set; }
+ ///
+ /// Formates a LogMessage to a String
+ ///
+ /// Formated String
+ public override String ToString() {
+ return "[" + this.Date.ToString("R") + "]: " + this.Level.ToString() + " "+ this.Location + ", " + this.Message;
+ }
+ ///
+ /// Formates a LogMessage to a String
+ ///
+ /// Enables the output of the location
+ /// Enables the output of the date
+ /// Formated String
+ public String ToString(Boolean classNames, Boolean timeStamps) {
+ return (timeStamps ? "[" + this.Date.ToString("R") + "]: " + this.Level.ToString() + " " : "") + (classNames ? this.Location + ", " : "") + this.Message;
+ }
+ }
+
+ private List loglist = new List();
+
+ public delegate void LogEvent(Object sender, LogEventArgs e);
+ public enum LogLevel : Int32 {
+ Debug = 1,
+ Notice = 2,
+ Info = 4,
+ Warn = 8,
+ Error = 16
+ }
+
+ public event LogEvent EventDebug;
+ public event LogEvent EventNotice;
+ public event LogEvent EventInfo;
+ public event LogEvent EventWarn;
+ public event LogEvent EventError;
+ public event LogEvent EventLog;
+
+ ///
+ /// Get the Complete Log
+ ///
+ public List GetLog(LogLevel level, Boolean classNames, Boolean timeStamps) {
+ List ret = new List();
+ foreach (LogObject t in this.loglist) {
+ if (t.Level >= level) {
+ ret.Add(t.ToString(classNames, timeStamps));
+ }
+ }
+ return ret;
+ }
+
+ ///
+ /// Put a message in the log
+ ///
+ /// Where the event arrives
+ /// The logmessage itselfs
+ /// Level of the message
+ protected void AddLog(String location, String message, LogLevel level)
+ {
+ this.AddLog(location, message, level, DateTime.Now);
+ }
+
+ ///
+ /// Put a message in the log
+ ///
+ /// Where the event arrives
+ /// The logmessage itselfs
+ /// Level of the message
+ /// Date of the message
+ protected void AddLog(String location, String message, LogLevel level, DateTime date)
+ {
+ LogEventArgs e = new LogEventArgs(location, message, level, date);
+ if (EventDebug != null && level >= LogLevel.Debug) {
+ EventDebug(this, e);
+ }
+ if (EventNotice != null && level >= LogLevel.Notice) {
+ EventNotice(this, e);
+ }
+ if (EventInfo != null && level >= LogLevel.Info) {
+ EventInfo(this, e);
+ }
+ if (EventWarn != null && level >= LogLevel.Warn) {
+ EventWarn(this, e);
+ }
+ if (EventError != null && level >= LogLevel.Error) {
+ EventError(this, e);
+ }
+ EventLog?.Invoke(this, e);
+
+ this.loglist.Add(new LogObject(date, location, message, level));
+ }
+ }
+}
diff --git a/Utils/Utils/OwnView.cs b/Utils/Utils/OwnView.cs
new file mode 100644
index 0000000..bd30612
--- /dev/null
+++ b/Utils/Utils/OwnView.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace BlubbFish.Utils {
+ public abstract class OwnView {
+
+ protected OwnView() { }
+ ///
+ /// Called if the Oberver (Model) updates its View
+ ///
+ public abstract void Update();
+ ///
+ /// Called if view is viewed
+ ///
+ //protected abstract void Init();
+ ///
+ /// Called if Form is Disposed
+ ///
+ public abstract void Dispose();
+ }
+}
diff --git a/Utils/Utils/Properties/AssemblyInfo.cs b/Utils/Utils/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..0e88670
--- /dev/null
+++ b/Utils/Utils/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+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 mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Utils")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("Utils")]
+[assembly: AssemblyCopyright("Copyright © 2014 - 25.09.2017")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("6f20376a-5c71-4979-9932-13c105d1c6e6")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+// Hauptversion
+// Nebenversion
+// Buildnummer
+// Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.5.2")]
+[assembly: AssemblyFileVersion("1.0.5.2")]
diff --git a/Utils/Utils/Updater.cs b/Utils/Utils/Updater.cs
new file mode 100644
index 0000000..fc4eb0e
--- /dev/null
+++ b/Utils/Utils/Updater.cs
@@ -0,0 +1,192 @@
+
+using System;
+using System.IO;
+using System.Net;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Xml;
+
+namespace BlubbFish.Utils {
+ public class Updater : OwnObject {
+ private static Updater instances;
+ private String url;
+ private VersionInfo[] versions;
+ private Thread t;
+
+ public struct VersionInfo {
+ public VersionInfo(Type type) {
+ this.Name = type.Assembly.GetName().Name;
+ this.Version = type.Assembly.GetName().Version.ToString();
+ this.Filename = type.Assembly.ManifestModule.Name;
+ this.GUID = ((GuidAttribute)type.Assembly.GetCustomAttribute(typeof(GuidAttribute))).Value;
+ this.HasUpdate = false;
+ }
+
+ public String Name { get; private set; }
+ public String Version { get; private set; }
+ public String Filename { get; private set; }
+ public String GUID { get; private set; }
+ public Boolean HasUpdate { get; set; }
+ }
+
+ public delegate void UpdateStatus(Object sender, UpdaterEventArgs e);
+ public delegate void UpdateFail(Object sender, UpdaterFailEventArgs e);
+
+ public event UpdateStatus UpdateResult;
+ public event UpdateFail ErrorRaised;
+
+ private Updater() { }
+
+ ///
+ /// Get Instance of Updater
+ ///
+ public static Updater Instance {
+ get {
+ if(instances == null) {
+ instances = new Updater();
+ }
+ return instances;
+ }
+ }
+
+ ///
+ /// Waits for the Result of the Updater thread.
+ ///
+ public void WaitForExit(Boolean exceuteUpdate = true) {
+ while (this.t.ThreadState == ThreadState.Running) { }
+ if(exceuteUpdate) {
+ if(File.Exists("update.bat")) {
+ System.Diagnostics.Process.Start("update.bat");
+ }
+ }
+ }
+
+ ///
+ /// Set Path to check for Updates
+ ///
+ /// HTTP URI
+ public void SetUpdateInfo(String url, VersionInfo[] versions) {
+ this.url = url;
+ this.versions = versions;
+ FileStream file = new FileStream("version.xml",FileMode.Create);
+ XmlTextWriter xml = new XmlTextWriter(file, Encoding.UTF8);
+ xml.WriteStartDocument();
+ xml.WriteWhitespace("\n");
+ xml.WriteStartElement("filelist");
+ xml.WriteWhitespace("\n");
+ foreach (VersionInfo version in versions) {
+ xml.WriteWhitespace("\t");
+ xml.WriteStartElement("file");
+ xml.WriteAttributeString("Version", version.Version);
+ xml.WriteAttributeString("Filename", version.Filename);
+ xml.WriteAttributeString("GUID", version.GUID);
+ xml.WriteString(version.Name);
+ xml.WriteEndElement();
+ xml.WriteWhitespace("\n");
+ }
+ xml.WriteEndElement();
+ xml.Flush();
+ file.Flush();
+ file.Close();
+ }
+
+ ///
+ /// Check for Updates
+ ///
+ ///
+ public void Check() {
+ if(this.url == "") {
+ throw new ArgumentException("Zuerst eine URL setzen!");
+ }
+ if(this.versions.Length == 0) {
+ throw new ArgumentException("Zuerst Dateien registrieren!");
+ }
+ if(this.UpdateResult == null) {
+ throw new ArgumentNullException("Zuerst das Update Event anhängen.");
+ }
+ this.t = new Thread(this.Runner);
+ this.t.Start();
+ }
+
+ private void Runner() {
+ Thread.Sleep(1000);
+ try {
+ Stream stream = WebRequest.Create(this.url + "version.xml").GetResponse().GetResponseStream();
+ String content = new StreamReader(stream).ReadToEnd();
+ Boolean update = false;
+ XmlDocument doc = new XmlDocument();
+ doc.LoadXml(content);
+ foreach (XmlNode node in doc.DocumentElement.ChildNodes) {
+ String guid = node.Attributes["GUID"].Value;
+ String version = node.Attributes["Version"].Value;
+ for(Int32 i=0;i
+ /// Update the file
+ ///
+ /// Updates the Programm after it has been closed
+ ///
+ public Boolean Update(Boolean afterExit = true) {
+ try {
+ if (afterExit) {
+ this.UpdateAfter();
+ } else {
+ this.UpdateNow();
+ }
+ } catch (Exception e) {
+ this.ErrorRaised?.Invoke(this, new UpdaterFailEventArgs(e));
+ return false;
+ }
+ return true;
+ }
+
+ private void UpdateAfter() {
+ this.UpdateNow(true);
+ StreamWriter update = new StreamWriter("update.bat", false);
+ update.WriteLine("echo off");
+ update.WriteLine("echo \"Warte 10s\"");
+ update.WriteLine("ping 127.0.0.1 -n 10");
+ update.WriteLine("echo \"Kopiere Dateien....\"");
+ foreach (VersionInfo file in this.versions) {
+ if (file.HasUpdate) {
+ update.WriteLine("echo \"Kopiere " + file.Filename + "\"");
+ update.WriteLine("del " + file.Filename);
+ update.WriteLine("move " + file.Filename + "_ " + file.Filename);
+ }
+ }
+ update.WriteLine("start cmd /C ping 127.0.0.1 -n 10 & del update.bat");
+ update.Flush();
+ update.Close();
+ }
+
+ private void UpdateNow(Boolean forAfter = false) {
+ foreach (VersionInfo file in this.versions) {
+ if (file.HasUpdate) {
+ Stream stream = WebRequest.Create(this.url + file.Filename).GetResponse().GetResponseStream();
+ FileStream target = new FileStream(file.Filename + (forAfter ? "_" : ""), FileMode.Create);
+ stream.CopyTo(target);
+ target.Flush();
+ target.Close();
+ }
+ }
+ }
+ }
+}
diff --git a/Utils/Utils/Utils.csproj b/Utils/Utils/Utils.csproj
new file mode 100644
index 0000000..61274ab
--- /dev/null
+++ b/Utils/Utils/Utils.csproj
@@ -0,0 +1,63 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {FAC8CE64-BF13-4ECE-8097-AEB5DD060098}
+ Library
+ Properties
+ BlubbFish.Utils
+ Utils
+ v4.5
+ 512
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Utils/Utils/bin/Release/Utils.dll b/Utils/Utils/bin/Release/Utils.dll
new file mode 100644
index 0000000..28f5d3d
Binary files /dev/null and b/Utils/Utils/bin/Release/Utils.dll differ
diff --git a/ebbits/AdvancedServo-simple/Arduino/AbstractArduino.cs b/ebbits/AdvancedServo-simple/Arduino/AbstractArduino.cs
new file mode 100644
index 0000000..54290cf
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Arduino/AbstractArduino.cs
@@ -0,0 +1,114 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.IO.Ports;
+using System.Text.RegularExpressions;
+
+namespace ebbits.Arduino {
+ abstract class AbstractArduino {
+ protected SerialPort arduino;
+ protected LinkedList readStack = new LinkedList();
+ protected void init(string port) {
+ arduino = new SerialPort(port, 57600);
+ arduino.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
+ arduino.Open();
+ arduino.WriteLine("");
+
+ }
+ private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
+ SerialPort sp = (SerialPort)sender;
+ string s = sp.ReadLine();
+ Logger.Serial("in", s);
+ if(ArduinoInput.check(s)) {
+ readStack.AddLast(new ArduinoInput(s));
+ }
+ }
+ protected void serialSend(char key, byte pos, int val) {
+ char c = ArduinoInput.checksum(key + pos.ToString() + "=" + val.ToString());
+ string s = "*" + key + pos.ToString() + "=" + val + "$" + c + "#";
+ arduino.WriteLine(s);
+ Logger.Serial("out", s);
+ }
+
+ protected ArduinoInput getInput(char key, byte id = 255) {
+ LinkedList.Enumerator e = readStack.GetEnumerator();
+ try {
+ while(e.MoveNext()) {
+ if((e.Current.key == key && e.Current.id == id) || (id == 255 && e.Current.key == key)) {
+ ArduinoInput a = e.Current;
+ readStack.Remove(a);
+ return a;
+ }
+ }
+ } catch(InvalidOperationException) {
+ return null;
+ }
+ return null;
+ }
+
+ protected ArduinoInput getInputWait(char key, byte id = 255) {
+ while(true) {
+ ArduinoInput a = getInput(key, id);
+ if(a != null) {
+ return a;
+ }
+ System.Threading.Thread.Sleep(1);
+ }
+ }
+
+ internal void clearStack() {
+ readStack.Clear();
+ }
+
+ internal void clearStack(char key) {
+ LinkedList.Enumerator e = readStack.GetEnumerator();
+ try {
+ while(e.MoveNext()) {
+ if(e.Current.key == key) {
+ readStack.Remove(e.Current);
+ }
+ }
+ } catch(InvalidOperationException) {
+ return;
+ }
+ }
+ }
+ class ArduinoInput {
+ public ArduinoInput(string indata) {
+ string reg = "\\*([a-z])(\\d)=([a-fA-F0-9]*)\\$(.)#";
+ Match m = Regex.Match(indata, reg);
+ this.key = m.Groups[1].ToString().ToCharArray()[0];
+ this.id = byte.Parse(m.Groups[2].ToString());
+ string val = m.Groups[3].ToString().ToUpper();
+ if(val == "") {
+ this.value = 0;
+ } else if(val.IndexOfAny(new char[] { 'A', 'B', 'C', 'D', 'E', 'F' }) != -1) {
+ this.value = Int64.Parse(val, System.Globalization.NumberStyles.HexNumber);
+ } else {
+ this.value = Int64.Parse(val);
+ }
+ }
+
+ public static char checksum(String data) {
+ char c = '$';
+ foreach(char t in data) {
+ c = (char)(c ^ t);
+ }
+ return c;
+ }
+
+ public static bool check(string indata) {
+ string reg = "\\*([a-z]\\d)=([a-fA-F0-9]*)\\$(.)#";
+ Match m = Regex.Match(indata, reg);
+ if(!m.Success) {
+ return false;
+ }
+ String rec = m.Groups[1].ToString() + "=" + m.Groups[2].ToString();
+ return (ArduinoInput.checksum(rec) == m.Groups[3].ToString().ToCharArray()[0]);
+ }
+
+ public char key { get; private set; }
+ public byte id { get; private set; }
+ public Int64 value { get; private set; }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Arduino/MainArduino.cs b/ebbits/AdvancedServo-simple/Arduino/MainArduino.cs
new file mode 100644
index 0000000..712e99c
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Arduino/MainArduino.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+
+namespace ebbits.Arduino {
+ class MainArduino : AbstractArduino {
+ public const int ON = 1;
+ public const int OFF = 0;
+ public const int RED = 2;
+ public const int WHITE = 7;
+
+ public MainArduino(string port) {
+ init(port);
+ trainOn(1);
+ }
+
+ public void setLaser(byte p) {
+ serialSend('l', 1, p);
+ }
+
+ public void setColor(byte p) {
+ serialSend('c', 1, p);
+ }
+
+ public void trainOn(byte dir) {
+ serialSend('p', 2, 70); //Speed = 1
+ changeDir(dir); //Richtung = 1
+ serialSend('b', 2, 1); //Bremse = an
+ }
+
+ public void trainMove(byte speed) {
+ serialSend('b', 2, 0); //Bremse aus
+ serialSend('p', 2, speed);
+ }
+
+ internal void changeDir(byte dir) {
+ serialSend('d', 2, dir); //Richtung = 0
+ }
+
+ public bool readStop(char key, byte id) {
+ ArduinoInput a = base.getInputWait(key, id);
+ return true;
+ }
+
+ public void measureAndStop(char key, byte id) {
+ System.Threading.Thread t = new System.Threading.Thread(current_runnter);
+ t.Start();
+ this.readStop(key, id);
+ t.Abort();
+ base.clearStack('u');
+ }
+
+ private void current_runnter(object obj) {
+ DateTime t = DateTime.Now;
+ float current = 0;
+ while(true) {
+ long c = readCurrent();
+ current += ((float)c / 1000 * 12 * (DateTime.Now.Ticks - t.Ticks)) / 1000000;
+ t = DateTime.Now;
+ Logger.Info("Train Watt: " + current.ToString());
+ System.Threading.Thread.Sleep(100);
+ }
+ }
+
+ public long whereRead() {
+ serialSend('q', 0, 0);
+ ArduinoInput a = base.getInputWait('q');
+ return a.value;
+ }
+
+ public long readCurrent() {
+ serialSend('u', 1, 0);
+ ArduinoInput a = base.getInputWait('u');
+ return a.value;
+ }
+
+ public bool findStart() {
+ changeDir(0);
+ if(this.whereRead() == 0) {
+ trainMove(70);
+ System.Threading.Thread.Sleep(3000);
+ }
+ if(this.whereRead() == 0) {
+ changeDir(1);
+ System.Threading.Thread.Sleep(3000);
+ }
+ if(this.whereRead() == 0) {
+ trainOn(1);
+ return false;
+ }
+ trainOn(1);
+ changeDir(0);
+ Logger.Info("Lock gefunden und stehe auf: " + this.whereRead());
+ base.clearStack();
+ switch(this.whereRead()) {
+ case 6:
+ Logger.Info("Fahre von 6 nach 5");
+ trainMove(70);
+ readStop('r',4);
+ trainMove(70);
+ readStop('r',5);
+ break;
+ case 4:
+ Logger.Info("Fahre von 4 nach 5");
+ trainMove(70);
+ readStop('r',5);
+ break;
+ case 3:
+ Logger.Info("Fahre von 3 nach 5");
+ trainMove(70);
+ readStop('r',2);
+ trainMove(70);
+ readStop('r',1);
+ trainMove(70);
+ readStop('r',5);
+ break;
+ case 2:
+ Logger.Info("Fahre von 2 nach 5");
+ trainMove(70);
+ readStop('r',1);
+ trainMove(70);
+ readStop('r',5);
+ break;
+ case 1:
+ Logger.Info("Fahre von 1 nach 5");
+ trainMove(70);
+ readStop('r',5);
+ break;
+ }
+ trainOn(1);
+ Logger.Info("Stehe nun auf: " + this.whereRead());
+ return (this.whereRead() == 5);
+ }
+
+ public bool trainSwitchIsOff() {
+ serialSend('s', 0, 0);
+ ArduinoInput a = base.getInputWait('s');
+ return a.value == 0;
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Logger.cs b/ebbits/AdvancedServo-simple/Logger.cs
new file mode 100644
index 0000000..02a4df3
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Logger.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ebbits {
+ class Logger {
+ public static void Info(string msg) {
+ Logger.Message(msg, "INFO");
+ }
+ private static void Message(string msg, string type) {
+ DateTime d = DateTime.Now;
+ Console.WriteLine("[" + d.ToLongTimeString() + "." + d.Millisecond.ToString().PadLeft(3,'0') + "] " + type + ": " + msg);
+ }
+
+ public static void Notice(string msg) {
+ Logger.Message(msg, "NOTICE");
+ }
+
+ public static void Warn(string msg) {
+ Logger.Message(msg, "WARN");
+ }
+
+ public static void Message(string msg) {
+ Logger.Message(msg, "MESSAGE");
+ }
+
+ public static bool LogSerial { get; set; }
+
+ public static void Serial(string dir, string msg) {
+ if(LogSerial) {
+ Logger.Message(msg, "SERIAL "+dir.ToUpper());
+ }
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Program.cs b/ebbits/AdvancedServo-simple/Program.cs
new file mode 100644
index 0000000..eec6e92
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Program.cs
@@ -0,0 +1,100 @@
+/*- AdvancedServo simple -
+0****************************************************************************************
+ * This example simply displays the Phidget AdvancedServo serial number when it is
+ * attached and sets the servo positions, velocity, and acceleration to 0. Then we will
+ * do a simple simulation of a basic movement of a servo motor at 100.00 velocity and
+ * 100.00 Acceleration. I decided to leave out the current change event handler for
+ * easier readability. For a more detailed example, see the Servo-full example.
+ *
+ * Please note that this example was designed to work with only one Phidget AdvanceServo
+ * connected.
+ * For an example showing how to use two Phidgets of the same time concurrently, please see the
+ * Servo-multi example in the Servo Examples.
+
+ * Copyright 2007 Phidgets Inc. All rights reserved.*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+//Needed for the AdvancedServo class, phidget base classes, and PhidgetException class
+
+//Needed for the event handling classes
+using Phidgets.Events;
+//Using this simply for the sleep() method so that the for loop will wail for the motor
+//to finish moving to the previous new position before setting a new position
+using System.Threading;
+
+
+
+using ebbits.Robots;
+using ebbits.Arduino;
+
+namespace ebbits {
+ class Program {
+ static void Main(string[] args) {
+ Logger.LogSerial = false;
+ MainArduino a = new MainArduino("COM50");
+ //AbstractRobot l = new LaserBot(169861, a);
+ AbstractRobot p = new PaintBot(169889, a);
+ //AbstractRobot g = new GlassBot(169887);
+
+ Console.WriteLine("All Engaged. Press Key to Start.");
+ Console.ReadLine();
+
+ while(true) {
+ a.clearStack();
+ a.trainOn(1);
+ if(a.whereRead() != 5) {
+ Logger.Warn("Achtung! Steht nicht auf Start!");
+ //Console.ReadLine();
+ if(!a.findStart()) {
+ Logger.Warn("ABBRUCH! Konnte die Bahn nicht Finden oder einstellen!");
+ //Console.ReadLine();
+ continue;
+ }
+ }
+ while(a.trainSwitchIsOff()) {
+ Thread.Sleep(100);
+ }
+
+ Logger.Message("Move from Start to Welding Pos");
+ a.trainMove(70);
+ a.measureAndStop('r', 1);
+
+ Logger.Message("Welding");
+ Thread.Sleep(1000);//l.run();
+
+ Logger.Message("Move from Welding to Paint Pos");
+ a.trainMove(68);
+ a.measureAndStop('r', 2);
+
+ Logger.Message("Paint");
+ p.run();
+ Console.ReadLine();
+
+ Logger.Message("Move from Paint to Glas Pos");
+ a.trainMove(68);
+ a.measureAndStop('r', 3);
+
+ Logger.Message("Glas");
+ Thread.Sleep(1000);//g.run();
+
+ Logger.Message("Move from Glas to Turn around Pos");
+ a.trainMove(78);
+ a.measureAndStop('r',6);
+
+ Logger.Message("Turn aroud and move from Turn around to Waiting Pos");
+ System.Threading.Thread.Sleep(500);
+ a.changeDir(0);
+ a.trainMove(90);
+ a.readStop('r',4);
+
+ Logger.Message("Move from Waiting Pos to Start Pos");
+ a.trainMove(90);
+ a.readStop('r', 5);
+
+ Logger.Info("Runde zuende!");
+ }
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Properties/AssemblyInfo.cs b/ebbits/AdvancedServo-simple/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..e53ca52
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("AdvancedServo-simple")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Phidgets Inc.")]
+[assembly: AssemblyProduct("AdvancedServo-simple")]
+[assembly: AssemblyCopyright("Copyright © Phidgets Inc. 2007")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("35c7dfbc-b70d-4603-9844-3fd32bce5b60")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/ebbits/AdvancedServo-simple/Robots/AbstractRobot.cs b/ebbits/AdvancedServo-simple/Robots/AbstractRobot.cs
new file mode 100644
index 0000000..86e80b2
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Robots/AbstractRobot.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Phidgets;
+using System.Threading;
+
+namespace ebbits.Robots {
+ public abstract class AbstractRobot {
+ protected AdvancedServo servo;
+ protected int cservos;
+ protected string name;
+ private Thread t;
+ protected void init(int id) {
+ servo = new AdvancedServo();
+ servo.open(id);
+ Logger.Info("Waiting for Servo \"" + id + "\" is attached");
+ servo.waitForAttachment();
+ if(!servo.Attached) { throw new AccessViolationException("Robot not Found"); }
+ }
+ public abstract void run();
+ protected void setPosition(int[] pos, int speed) {
+ for(int i = 0; i < cservos; i++) {
+ if(pos[i] != -1) {
+ AdvancedServoServo s = servo.servos[i+ 5 - cservos];
+ s.Acceleration = speed;
+ s.Position = pos[i];
+ }
+ }
+
+ bool waiting = true;
+ while(waiting) {
+ waiting = false;
+ for(int i = 0; i < cservos; i++) {
+ if(pos[i] != -1) {
+ AdvancedServoServo s = servo.servos[i + 5 - cservos];
+ s.Position = pos[i];
+ try {
+ if(Math.Abs(s.Position - pos[i]) > 0.01) {
+ waiting = true;
+ }
+ } catch(PhidgetException) {
+ Logger.Warn("Exeption!");
+ s.Position = pos[i];
+ }
+ Thread.Sleep(10);
+ }
+ }
+ }
+ }
+ protected void setStartPosition(int[] positions, int sleep) {
+ for(int i = 0; i < cservos; i++) {
+ AdvancedServoServo s = servo.servos[i + 5 - cservos];
+ s.Type = ServoServo.ServoType.TOWERPRO_MG90;
+ s.Acceleration = 10000;
+ s.VelocityLimit = 200;
+ s.Position = positions[i];
+ s.Engaged = true;
+ }
+ Thread.Sleep(sleep);
+ }
+ protected void shutdownServo() {
+ for(int i = 0; i < cservos; i++) {
+ servo.servos[i + 5 - cservos].Engaged = false;
+ }
+ if(t.IsAlive) {
+ t.Abort();
+ }
+ }
+
+ protected void startPowerMess() {
+ this.t = new System.Threading.Thread(current_runnter);
+ t.Start();
+ }
+
+ private void current_runnter(object obj) {
+ DateTime t = DateTime.Now;
+ double current = 0;
+ while(true) {
+ double c = 0;
+ for(int i = 0; i < 5; i++) {
+ c += this.servo.servos[0].Current;
+ }
+ current += (c * 12 * (DateTime.Now.Ticks - t.Ticks)) / 1000000;
+ t = DateTime.Now;
+ Logger.Info(this.name+" Watt: " + current.ToString());
+ System.Threading.Thread.Sleep(100);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/ebbits/AdvancedServo-simple/Robots/GlassBot.cs b/ebbits/AdvancedServo-simple/Robots/GlassBot.cs
new file mode 100644
index 0000000..a9096cf
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Robots/GlassBot.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace ebbits.Robots {
+ class GlassBot : AbstractRobot {
+ public GlassBot(int id) {
+ init(id);
+ this.cservos = 5;
+ base.name = "Glas";
+ }
+ public override void run() {
+ base.startPowerMess();
+ setStartPosition(new int[] { 20, 68, 175, 175, 20 }, 500);
+
+ setPosition(new int[] { 20, 68, 160, 162, 20 }, 400);
+ setPosition(new int[] { -1, 154, 88, 88, -1 }, 400);
+ setPosition(new int[] { -1, -1, 86, 116, 42 }, 200);
+ setPosition(new int[] { -1, -1, 77, -1, 48 }, 50);
+ setPosition(new int[] { 160, -1, -1, -1, -1 }, 200);
+ setPosition(new int[] { -1, -1, 85, -1, -1 }, 20);
+ setPosition(new int[] { -1, -1, -1, 106, -1 }, 200);
+ setPosition(new int[] { -1, -1, 118, 122, 174 }, 200);
+
+ setPosition(new int[] { -1, 13, -1, -1, -1 }, 300);
+ setPosition(new int[] { -1, -1, 90, 100, 20 }, 200);
+
+ setPosition(new int[] { -1, -1, 80, 94, 26 }, 20); // Fine Settings
+ System.Threading.Thread.Sleep(1000);
+ setPosition(new int[] { -1, -1, 90, 90, 20 }, 20); // Fine Lift
+
+ setPosition(new int[] { -1, -1, 103, 105, 80 }, 150);
+ setPosition(new int[] { -1, 154, 118, 122, 174 }, 300);
+ setPosition(new int[] { -1, -1, 86, 102, 42 }, 300);
+ setPosition(new int[] { -1, -1, 83, 113, 48 }, 100);
+ setPosition(new int[] { -1, -1, -1, 117, -1 }, 20);
+ setPosition(new int[] { 20, -1, 78, -1, -1 }, 150);
+ setPosition(new int[] { -1, -1, 81, 111, -1 }, 20);
+ setPosition(new int[] { -1, -1, 90, -1, -1 }, 100);
+
+ setPosition(new int[] { 20, 68, 160, 162, 20 }, 400);
+ setPosition(new int[] { 20, 68, 175, 175, 20 }, 400);
+
+ shutdownServo();
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Robots/LaserBot.cs b/ebbits/AdvancedServo-simple/Robots/LaserBot.cs
new file mode 100644
index 0000000..c2ca21f
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Robots/LaserBot.cs
@@ -0,0 +1,35 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ebbits.Arduino;
+
+namespace ebbits.Robots {
+ class LaserBot : AbstractRobot {
+ private Arduino.MainArduino Arduino;
+ public LaserBot(int id, MainArduino a) {
+ init(id);
+ base.cservos = 4;
+ this.Arduino = a;
+ base.name = "Laser";
+ }
+
+ override public void run() {
+ base.startPowerMess();
+
+ base.setStartPosition(new int[] {77, 175, 155, 84 }, 500);
+
+ base.setPosition(new int[] { 77, 157, 134, 84 }, 400);
+ base.setPosition(new int[] { 83, 96, 114, 44 }, 200);
+ Arduino.setLaser(MainArduino.ON);
+ base.setPosition(new int[] { 101, 91, 107, 45 }, 20);
+ base.setPosition(new int[] { 98, 78, 88, 49 }, 20);
+ base.setPosition(new int[] { 83, 82, 95, 46 }, 20);
+ base.setPosition(new int[] { 83, 96, 114, 44 }, 20);
+ Arduino.setLaser(MainArduino.OFF);
+ base.setPosition(new int[] { 77, 157, 134, 84 }, 400);
+ base.setPosition(new int[] { 77, 175, 155, 84 }, 400);
+
+ base.shutdownServo();
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/Robots/PaintBot.cs b/ebbits/AdvancedServo-simple/Robots/PaintBot.cs
new file mode 100644
index 0000000..eb45319
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/Robots/PaintBot.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using ebbits.Arduino;
+
+namespace ebbits.Robots {
+ class PaintBot : AbstractRobot {
+ private MainArduino Arduino;
+ public PaintBot(int id, MainArduino a) {
+ init(id);
+ this.cservos = 4;
+ this.Arduino = a;
+ base.name = "Paint";
+ }
+ public override void run() {
+ base.startPowerMess();
+ setStartPosition(new int[] {87, 175, 160, 92 }, 500);
+
+ setPosition(new int[] {87, 153, 138, 92 }, 400);
+ setPosition(new int[] {47, 101, 158, 48 }, 200);
+ Arduino.setColor(MainArduino.RED);
+ setPosition(new int[] {91, 122, 161, 78 }, 50);
+ Arduino.setColor(MainArduino.OFF);
+ setPosition(new int[] {-1, 140, -1, -1 }, 200);
+ setPosition(new int[] {-1, 71, 55, 110 }, 200);
+ setPosition(new int[] {-1, 43, 42, 175 }, 200);
+ Arduino.setColor(MainArduino.RED);
+ setPosition(new int[] { 79, 42, 39, -1 }, 50);
+ setPosition(new int[] { 68, 39, 30, -1 }, 50);
+ setPosition(new int[] { -1, 36, 20, -1 }, 50);
+ setPosition(new int[] { 64, -1, -1, -1 }, 50);
+ Arduino.setColor(MainArduino.OFF);
+ setPosition(new int[] {-1, 44, -1, 150 }, 200);
+ setPosition(new int[] {57, 68, 70, 139 }, 200);
+ Arduino.setColor(MainArduino.WHITE);
+ setPosition(new int[] {53, 74, 79, 158 }, 50);
+ setPosition(new int[] {89, 86, 98, 150 }, 50);
+ setPosition(new int[] {-1, 75, 85, 143 }, 50);
+ setPosition(new int[] { 57, 68, 70, 139 }, 50);
+ Arduino.setColor(MainArduino.OFF);
+ setPosition(new int[] { -1, 153, 138, 92 }, 400);
+ setPosition(new int[] { 87, 175, 160, 92 }, 400);
+
+ shutdownServo();
+ }
+ }
+}
diff --git a/ebbits/AdvancedServo-simple/ebbits.csproj b/ebbits/AdvancedServo-simple/ebbits.csproj
new file mode 100644
index 0000000..e097253
--- /dev/null
+++ b/ebbits/AdvancedServo-simple/ebbits.csproj
@@ -0,0 +1,64 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.50727
+ 2.0
+ {94AEADEA-85AF-4DBD-AA16-4BE165FF538B}
+ Exe
+ Properties
+ ebbits
+ AdvancedServo-simple
+ v2.0
+
+
+
+
+ 2.0
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+ False
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ebbits/ebbits.sln b/ebbits/ebbits.sln
new file mode 100644
index 0000000..5d4332f
--- /dev/null
+++ b/ebbits/ebbits.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2012
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ebbits", "AdvancedServo-simple\ebbits.csproj", "{94AEADEA-85AF-4DBD-AA16-4BE165FF538B}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {94AEADEA-85AF-4DBD-AA16-4BE165FF538B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {94AEADEA-85AF-4DBD-AA16-4BE165FF538B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {94AEADEA-85AF-4DBD-AA16-4BE165FF538B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {94AEADEA-85AF-4DBD-AA16-4BE165FF538B}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal