This commit is contained in:
2017-09-26 20:21:42 +02:00
parent e144bde202
commit 319ca0cbbb
194 changed files with 10149 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
#include <Rainbowduino.h>
#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);
}
}
}
+22
View File
@@ -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
@@ -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();
}
@@ -0,0 +1,92 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{C5F80730-F44F-4478-BDAE-6634EFC2CA88}</ProjectGuid>
<RootNamespace>Zeit_V2</RootNamespace>
<ProjectName>Zeit-V2</ProjectName>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>
</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>
</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<IncludePath>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)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>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)</AdditionalIncludeDirectories>
<ForcedIncludeFiles>C:\Users\schell\Documents\Arduino\Zeit-V2\Zeit-V2\__vm\.Zeit-V2.vsarduino.h;%(ForcedIncludeFiles)</ForcedIncludeFiles>
<IgnoreStandardIncludePath>false</IgnoreStandardIncludePath>
<PreprocessorDefinitions>__AVR_ATmega328p__;__AVR_ATmega328P__;F_CPU=16000000L;ARDUINO=10607;ARDUINO_AVR_UNO;ARDUINO_ARCH_AVR;__cplusplus=201103L;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<None Include="Zeit-V2.ino">
<FileType>CppCode</FileType>
<DeploymentContent>true</DeploymentContent>
</None>
</ItemGroup>
<ItemGroup>
<ClInclude Include="button.h" />
<ClInclude Include="display.h" />
<ClInclude Include="network.h" />
<ClInclude Include="programm.h" />
<ClInclude Include="rfid.h" />
<ClInclude Include="__vm\.Zeit-V2.vsarduino.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<None Include="Zeit-V2.ino" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="button.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="display.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="programm.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="rfid.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="__vm\.Zeit-V2.vsarduino.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
+27
View File
@@ -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;
}
+59
View File
@@ -0,0 +1,59 @@
#if !defined(DEBUG_FLAG)
#define DEBUG_FLAG false
#endif
#include <SoftwareSerial.h>
#if DEBUG_FLAG
#include <HardwareSerial.h>
#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);
}
+64
View File
@@ -0,0 +1,64 @@
#if !defined(DEBUG_FLAG)
#define DEBUG_FLAG false
#endif
#include <SPI.h>
#include <Ethernet2.h>
#if DEBUG_FLAG
#include <HardwareSerial.h>
#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
}
+194
View File
@@ -0,0 +1,194 @@
#if !defined(DEBUG_FLAG)
#define DEBUG_FLAG false
#endif
#include <HardwareSerial.h>
#include <Time.h>
#include <stdlib.h>
#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;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
#include <SoftwareSerial.h>
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 = "";
}
+46
View File
@@ -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
+47
View File
@@ -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();
}
/// <summary>
/// User klickt Doppelt auf das TrayIcon
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
internal static void Click_Tray(object sender, EventArgs e) {
Click_Open(sender, e);
}
/// <summary>
/// User klickt auf den Eintrag Öffnen
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
internal static void Click_Open(object sender, EventArgs e) {
window.execute();
}
/// <summary>
/// User klickt auf den Eintrag Beenden
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
internal static void Click_Quit(object sender, EventArgs e) {
tray.Dispose();
Application.Exit();
}
}
}
@@ -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();
}
}
}
@@ -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 {
/// <summary>
/// Current DB Engine
/// </summary>
public DatabaseEngine DatabaseEngine { get; protected set; }
/// <summary>
/// The database connection
/// </summary>
public DbConnection Connection { get; protected set; }
/// <summary>
/// Returns whether the Database connection is open
/// </summary>
public bool IsConnected {
get { return (Connection.State == ConnectionState.Open); }
}
/// <summary>
/// Returns the current conenction state of the database
/// </summary>
public ConnectionState State {
get { return Connection.State; }
}
/// <summary>
/// Gets the number of queries ran by this instance
/// </summary>
public int NumQueries = 0;
/// <summary>
/// Random, yes... But its used here when building queries dynamically
/// </summary>
protected static char Comma = ',';
/// <summary>
/// Indicates whether the disposed method was called
/// </summary>
protected bool IsDisposed = false;
/// <summary>
/// Constructor
/// </summary>
/// <param name="Engine">The string name, for the GetDatabaseEngine() method</param>
/// <param name="Host">The Database server IP Address</param>
/// <param name="Port">The Database server Port Number</param>
/// <param name="DatabaseName">The name of the database</param>
/// <param name="User">A username, with database privliages</param>
/// <param name="Pass">The password to the User</param>
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.");
}
}
/// <summary>
/// Destructor
/// </summary>
~DatabaseDriver() {
Dispose();
}
/// <summary>
/// Disposes the DB connection
/// </summary>
public void Dispose() {
if(Connection != null && !IsDisposed) {
try {
Connection.Close();
Connection.Dispose();
} catch(ObjectDisposedException) { }
IsDisposed = true;
}
}
/// <summary>
/// Opens the database connection
/// </summary>
public void Connect() {
if(Connection.State != ConnectionState.Open) {
try {
Connection.Open();
} catch(Exception e) {
throw new DbConnectException("Unable to etablish database connection", e);
}
}
}
/// <summary>
/// Closes the connection to the database
/// </summary>
public void Close() {
try {
if(Connection.State != ConnectionState.Closed)
Connection.Close();
} catch(ObjectDisposedException) { }
}
/// <summary>
/// Creates a new command to be executed on the database
/// </summary>
/// <param name="QueryString"></param>
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);
}
/// <summary>
/// Creates a DbParameter using the current Database engine's Parameter object
/// </summary>
/// <returns></returns>
public DbParameter CreateParam() {
if(DatabaseEngine == Database.DatabaseEngine.Sqlite)
return (new SQLiteParameter() as DbParameter);
else
return (new MySqlParameter() as DbParameter);
}
/// <summary>
/// Queries the database, and returns a result set
/// </summary>
/// <param name="Sql">The SQL Statement to run on the database</param>
/// <returns></returns>
public List<Dictionary<string, object>> Query(string Sql) {
return this.Query(Sql, new List<DbParameter>());
}
/// <summary>
/// Queries the database, and returns a result set
/// </summary>
/// <param name="Sql">The SQL Statement to run on the database</param>
/// <param name="Items">Additional parameters are parameter values for the query.
/// The first parameter replaces @P0, second @P1 etc etc.
/// </param>
/// <returns></returns>
public List<Dictionary<string, object>> Query(string Sql, params object[] Items) {
List<DbParameter> Params = new List<DbParameter>(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);
}
/// <summary>
/// Queries the database, and returns a result set
/// </summary>
/// <param name="Sql">The SQL Statement to run on the database</param>
/// <param name="Params">A list of sql params to add to the command</param>
/// <returns></returns>
public List<Dictionary<string, object>> Query(string Sql, List<DbParameter> Params) {
// Create our Rows result
List<Dictionary<string, object>> Rows = new List<Dictionary<string, object>>();
// 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<string, object> Row = new Dictionary<string, object>(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;
}
/// <summary>
/// Queries the database, and returns 1 row at a time until all rows are returned
/// </summary>
/// <param name="Sql">The SQL Statement to run on the database</param>
/// <returns></returns>
public IEnumerable<Dictionary<string, object>> 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<string, object> Row = new Dictionary<string, object>(Reader.FieldCount);
for(int i = 0; i < Reader.FieldCount; ++i)
Row.Add(Reader.GetName(i), Reader.GetValue(i));
yield return Row;
}
}
// Cleanup
Reader.Close();
}
}
/// <summary>
/// Executes a command, and returns 1 row at a time until all rows are returned
/// </summary>
/// <param name="Command">The database command to execute the reader on</param>
/// <returns></returns>
public IEnumerable<Dictionary<string, object>> 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<string, object> Row = new Dictionary<string, object>(Reader.FieldCount);
for(int i = 0; i < Reader.FieldCount; ++i)
Row.Add(Reader.GetName(i), Reader.GetValue(i));
yield return Row;
}
}
// Cleanup
Reader.Close();
}
}
/// <summary>
/// Executes a command, and returns the resulting rows
/// </summary>
/// <param name="Command">The database command to execute the reader on</param>
/// <returns></returns>
public List<Dictionary<string, object>> ExecuteReader(DbCommand Command) {
// Execute the query
List<Dictionary<string, object>> Rows = new List<Dictionary<string, object>>();
// 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<string, object> Row = new Dictionary<string, object>(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;
}
/// <summary>
/// Executes a statement on the database (Update, Delete, Insert)
/// </summary>
/// <param name="Sql">The SQL statement to be executes</param>
/// <returns>Returns the number of rows affected by the statement</returns>
public int Execute(string Sql) {
// Create the SQL Command
using(DbCommand Command = this.CreateCommand(Sql))
return Command.ExecuteNonQuery();
}
/// <summary>
/// Executes a statement on the database (Update, Delete, Insert)
/// </summary>
/// <param name="Sql">The SQL statement to be executed</param>
/// <param name="Params">A list of Sqlparameters</param>
/// <returns>Returns the number of rows affected by the statement</returns>
public int Execute(string Sql, List<DbParameter> 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();
}
}
/// <summary>
/// Executes a statement on the database (Update, Delete, Insert)
/// </summary>
/// <param name="Sql">The SQL statement to be executed</param>
/// <param name="Items">Additional parameters are parameter values for the query.
/// The first parameter replaces @P0, second @P1 etc etc.
/// </param>
/// <returns>Returns the number of rows affected by the statement</returns>
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();
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="Sql">The SQL statement to be executed</param>
/// <returns></returns>
public object ExecuteScalar(string Sql) {
// Increase Query Count
NumQueries++;
// Create the SQL Command
using(DbCommand Command = this.CreateCommand(Sql))
return Command.ExecuteScalar();
}
/// <summary>
/// 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.
/// </summary>
/// <param name="Sql">The SQL statement to be executed</param>
/// <param name="Params">A list of Sqlparameters</param>
/// <returns></returns>
public object ExecuteScalar(string Sql, List<DbParameter> 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();
}
}
/// <summary>
/// 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.
/// </summary>
/// <param name="Sql">The SQL statement to be executed</param>
/// <param name="Items"></param>
/// <returns></returns>
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();
}
}
/// <summary>
/// Begins a new database transaction
/// </summary>
/// <returns></returns>
public DbTransaction BeginTransaction() {
return Connection.BeginTransaction();
}
/// <summary>
/// Begins a new database transaction
/// </summary>
/// <param name="Level"></param>
/// <returns></returns>
public DbTransaction BeginTransaction(IsolationLevel Level) {
return Connection.BeginTransaction(Level);
}
/// <summary>
/// Converts a database string name to a DatabaseEngine type.
/// </summary>
/// <param name="Name"></param>
/// <returns></returns>
public static DatabaseEngine GetDatabaseEngine(string Name) {
return ((DatabaseEngine)Enum.Parse(typeof(DatabaseEngine), Name, true));
}
}
}
@@ -0,0 +1,8 @@
namespace TimeKeeper.Database
{
public enum DatabaseEngine
{
Sqlite,
Mysql,
}
}
@@ -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);
@@ -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<Dictionary<String, Object>> 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<String, Object> 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<Dictionary<String, Object>> getWorkOnDay(DateTime time) {
return base.Query("SELECT * FROM `work` WHERE date=@P0 ORDER BY `start` ASC", time.ToString("yyyy-MM-dd"));
}
/// <summary>
/// Returns the number of accounts in the database
/// </summary>
/// <returns></returns>
public int GetNumAccounts() {
var Row = base.Query("SELECT COUNT(id) AS count FROM accounts");
return Int32.Parse(Row[0]["count"].ToString());
}
}
}
@@ -0,0 +1,7 @@
using System;
namespace TimeKeeper.Exceptions {
class DbConnectException : Exception {
public DbConnectException(string Message, Exception Inner) : base(Message, Inner) { }
}
}
@@ -0,0 +1,7 @@
using System;
namespace TimeKeeper.Exceptions {
class IllegalDataException : Exception {
public IllegalDataException(string Message, Exception Inner) : base(Message, Inner) { }
}
}
@@ -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;
}
}
+75
View File
@@ -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<MyMessageArgs> 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);
}
}
}
+21
View File
@@ -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;
}
}
}
+31
View File
@@ -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<Database> {
private TDatabase database;
public Queue<WorkMessage> 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);
}
}
}
}
+137
View File
@@ -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<Tray> {
private Boolean isConnectedValue = false;
private TimeSpan OffsetTimeValue = new TimeSpan();
private UDPListener network;
private Thread setTimeThread;
private InIReader settingsfile;
private FileLogger sLogger;
private Queue<WorkMessage> MessagesValue = new Queue<WorkMessage>();
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<WorkMessage> 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;
}
}
}
+19
View File
@@ -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<Window> {
private Window() {
this.init();
}
override protected void init() {
}
}
}
@@ -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;
}
}
}
@@ -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;
}
}
}
+21
View File
@@ -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);
}
}
}
}
@@ -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")]
+103
View File
@@ -0,0 +1,103 @@
//------------------------------------------------------------------------------
// <auto-generated>
// 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.
// </auto-generated>
//------------------------------------------------------------------------------
namespace TimeKeeper.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// 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() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[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;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
/// </summary>
internal static System.Drawing.Icon IconMain {
get {
object obj = ResourceManager.GetObject("IconMain", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap MenuImagesQuit {
get {
object obj = ResourceManager.GetObject("MenuImagesQuit", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
/// </summary>
internal static System.Drawing.Icon TrayIconConnected {
get {
object obj = ResourceManager.GetObject("TrayIconConnected", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Icon ähnlich wie (Symbol).
/// </summary>
internal static System.Drawing.Icon TrayIconDisconnected {
get {
object obj = ResourceManager.GetObject("TrayIconDisconnected", resourceCulture);
return ((System.Drawing.Icon)(obj));
}
}
}
}
@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="IconMain" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\main.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="MenuImagesQuit" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\door_open.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TrayIconConnected" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\main_con.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
<data name="TrayIconDisconnected" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\Resources\Icons\main_dis.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 843 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+123
View File
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{25F58397-71CB-4298-979E-BAACE80C61CB}</ProjectGuid>
<OutputType>WinExe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>TimeKeeper</RootNamespace>
<AssemblyName>TimeKeeper</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>TimeKeeper.Program</StartupObject>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>Resources\Icons\main.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="MySql.Data">
<HintPath>..\lib\MySql.Data.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data.SQLite, Version=1.0.84.0, Culture=neutral, PublicKeyToken=db937bc2d44ff139, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\lib\System.Data.SQLite.dll</HintPath>
</Reference>
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Controller\CTray.cs" />
<Compile Include="Controller\CWindow.cs" />
<Compile Include="Database\DatabaseDriver.cs" />
<Compile Include="Database\DatabaseEngine.cs" />
<Compile Include="Database\TDatabase.cs" />
<Compile Include="Exceptions\DbConnectException.cs" />
<Compile Include="Exceptions\IllegalDataException.cs" />
<Compile Include="Misc\UDPListener.cs" />
<Compile Include="Misc\Utils.cs" />
<Compile Include="Models\MDatabase.cs" />
<Compile Include="Models\MTray.cs" />
<Compile Include="Models\MWindow.cs" />
<Compile Include="Models\Types\MyMessageArgs.cs" />
<Compile Include="Models\Types\WorkMessage.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Misc\StaticConfig.cs" />
<Compile Include="View\ViewWindowForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="View\ViewWindowForm.Designer.cs">
<DependentUpon>ViewWindowForm.cs</DependentUpon>
</Compile>
<Compile Include="View\VTray.cs" />
<Compile Include="View\VWindow.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Utils\Utils\Utils.csproj">
<Project>{fac8ce64-bf13-4ece-8097-aeb5dd060098}</Project>
<Name>Utils</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<None Include="Resources\Icons\main.ico" />
<None Include="settings.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Database\SQL\MySQL.Install.sql" />
<Content Include="Resources\Icons\door_open.png" />
<Content Include="Resources\Icons\main_con.ico" />
<Content Include="Resources\Icons\main_dis.ico" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+87
View File
@@ -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);
}
}
}
+35
View File
@@ -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; }
}
}
+33
View File
@@ -0,0 +1,33 @@
namespace TimeKeeper.View {
partial class ViewWindowForm {
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing) {
if(disposing && (components != null)) {
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent() {
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Text = "ViewWindowForm";
}
#endregion
}
}
@@ -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;
}
}
}
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,2 @@
[general]
comport=COM4
+11
View File
@@ -0,0 +1,11 @@
[general]
port=28654
arduinoport=25987
[database]
engine=Mysql
host=localhost
port=3306
db=worktime
user=root
pass=mafia
Binary file not shown.
Binary file not shown.